summaryrefslogtreecommitdiffstats
path: root/webapp/components/navbar.jsx
diff options
context:
space:
mode:
Diffstat (limited to 'webapp/components/navbar.jsx')
-rw-r--r--webapp/components/navbar.jsx134
1 files changed, 120 insertions, 14 deletions
diff --git a/webapp/components/navbar.jsx b/webapp/components/navbar.jsx
index 21ca53649..d4968986e 100644
--- a/webapp/components/navbar.jsx
+++ b/webapp/components/navbar.jsx
@@ -17,6 +17,7 @@ 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 PreferenceStore from 'stores/preference_store.jsx';
import Client from 'utils/web_client.jsx';
import * as AsyncClient from 'utils/async_client.jsx';
@@ -34,6 +35,8 @@ import {Link, browserHistory} from 'react-router';
import React from 'react';
+import * as GlobalActions from 'actions/global_actions.jsx';
+
export default class Navbar extends React.Component {
constructor(props) {
super(props);
@@ -50,6 +53,12 @@ export default class Navbar extends React.Component {
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.compareByDisplayName = this.compareByDisplayName.bind(this);
+
const state = this.getStateFromStores();
state.showEditChannelPurposeModal = false;
state.showEditChannelHeaderModal = false;
@@ -72,10 +81,14 @@ export default class Navbar extends React.Component {
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();
@@ -150,6 +163,96 @@ export default class Navbar extends React.Component {
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 = this.state.channel;
+ let curIndex = -1;
+ for (let i = 0; i < allChannels.length; i++) {
+ if (allChannels[i].id === curChannel.id) {
+ curIndex = i;
+ }
+ }
+ let nextChannel = curChannel;
+ let nextIndex = curIndex;
+ if (e.keyCode === Constants.KeyCodes.DOWN) {
+ nextIndex = curIndex + 1;
+ } else if (e.keyCode === Constants.KeyCodes.UP) {
+ nextIndex = curIndex - 1;
+ }
+ nextChannel = allChannels[Utils.mod(nextIndex, allChannels.length)];
+ 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 = this.state.channel;
+ let curIndex = -1;
+ for (let i = 0; i < allChannels.length; i++) {
+ if (allChannels[i].id === curChannel.id) {
+ curIndex = i;
+ }
+ }
+ let nextChannel = curChannel;
+ let nextIndex = curIndex;
+ let count = 0;
+ let increment = 0;
+ if (e.keyCode === Constants.KeyCodes.UP) {
+ increment = -1;
+ } else if (e.keyCode === Constants.KeyCodes.DOWN) {
+ increment = 1;
+ }
+ let unreadCounts = ChannelStore.getUnreadCount(allChannels[nextIndex].id);
+ while (count < allChannels.length && unreadCounts.msgs === 0 && unreadCounts.mentions === 0) {
+ nextIndex += increment;
+ count++;
+ nextIndex = Utils.mod(nextIndex, allChannels.length);
+ unreadCounts = ChannelStore.getUnreadCount(allChannels[nextIndex].id);
+ }
+ if (unreadCounts.msgs !== 0 || unreadCounts.mentions !== 0) {
+ nextChannel = allChannels[nextIndex];
+ GlobalActions.emitChannelClickEvent(nextChannel);
+ }
+ }
+ }
+ getDisplayedChannels() {
+ const allChannels = ChannelStore.getChannels().sort(this.compareByName);
+ const publicChannels = allChannels.filter((channel) => channel.type === Constants.OPEN_CHANNEL);
+ const privateChannels = allChannels.filter((channel) => channel.type === Constants.PRIVATE_CHANNEL);
+
+ const preferences = PreferenceStore.getCategory(Constants.Preferences.CATEGORY_DIRECT_CHANNEL_SHOW);
+
+ const directChannels = [];
+ const directNonTeamChannels = [];
+ for (const [name, value] of preferences) {
+ if (value !== 'true') {
+ continue;
+ }
+
+ const directChannel = allChannels.find(Utils.isDirectChannelForUser.bind(null, name));
+ directChannel.display_name = Utils.displayUsername(name);
+
+ if (UserStore.hasTeamProfile(name)) {
+ directChannels.push(directChannel);
+ } else {
+ directNonTeamChannels.push(directChannel);
+ }
+ }
+
+ directChannels.sort(this.compareByDisplayName);
+ directNonTeamChannels.sort(this.compareByDisplayName);
+
+ return publicChannels.concat(privateChannels).concat(directChannels).concat(directNonTeamChannels);
+ }
+ compareByName(a, b) {
+ return a.name.localeCompare(b.name);
+ }
+ compareByDisplayName(a, b) {
+ return a.display_name.localeCompare(b.display_name);
+ }
createDropdown(channel, channelTitle, isAdmin, isDirect, popoverContent) {
if (channel) {
var viewInfoOption = (
@@ -218,20 +321,23 @@ export default class Navbar extends React.Component {
</li>
);
- leaveChannelOption = (
- <li role='presentation'>
- <a
- role='menuitem'
- href='#'
- onClick={this.handleLeave}
- >
- <FormattedMessage
- id='navbar.leave'
- defaultMessage='Leave Channel'
- />
- </a>
- </li>
- );
+ const canLeave = channel.type === Constants.PRIVATE_CHANNEL ? this.state.userCount > 1 : true;
+ if (canLeave) {
+ leaveChannelOption = (
+ <li role='presentation'>
+ <a
+ role='menuitem'
+ href='#'
+ onClick={this.handleLeave}
+ >
+ <FormattedMessage
+ id='navbar.leave'
+ defaultMessage='Leave Channel'
+ />
+ </a>
+ </li>
+ );
+ }
}
var manageMembersOption;