From 2ccf5bbaa2421c03cf932431fc0247b43b48d774 Mon Sep 17 00:00:00 2001 From: David Lu Date: Mon, 16 May 2016 19:08:59 -0400 Subject: PLT-2784 Channel Navigation Shortcuts (#2979) * Completed shortcuts * Fixed up logic * Removed shortcut conflicts * Added code to limit channel navigation within group * Made code conform to user display, fixed minor logic * Completed shortcuts * Fixed up logic * Removed shortcut conflicts * Added code to limit channel navigation within group * Made code conform to user display, fixed minor logic --- webapp/components/create_comment.jsx | 4 +- webapp/components/create_post.jsx | 4 +- webapp/components/navbar.jsx | 79 ++++++++++++++++++++++++++++++++++++ 3 files changed, 83 insertions(+), 4 deletions(-) diff --git a/webapp/components/create_comment.jsx b/webapp/components/create_comment.jsx index 8a078eb73..771a8ef3a 100644 --- a/webapp/components/create_comment.jsx +++ b/webapp/components/create_comment.jsx @@ -205,7 +205,7 @@ class CreateComment extends React.Component { return; } - if (!e.ctrlKey && !e.metaKey && e.keyCode === KeyCodes.UP && this.state.messageText === '') { + if (!e.ctrlKey && !e.metaKey && !e.altKey && !e.shiftKey && e.keyCode === KeyCodes.UP && this.state.messageText === '') { e.preventDefault(); const lastPost = PostStore.getCurrentUsersLatestPost(this.props.channelId, this.props.rootId); @@ -224,7 +224,7 @@ class CreateComment extends React.Component { }); } - if ((e.ctrlKey || e.metaKey) && e.keyCode === KeyCodes.UP) { + if ((e.ctrlKey || e.metaKey) && !e.altKey && !e.shiftKey && e.keyCode === KeyCodes.UP) { const lastPost = PostStore.getCurrentUsersLatestPost(this.props.channelId, this.props.rootId); if (!lastPost) { return; diff --git a/webapp/components/create_post.jsx b/webapp/components/create_post.jsx index 32f1b387a..3f319bb58 100644 --- a/webapp/components/create_post.jsx +++ b/webapp/components/create_post.jsx @@ -351,7 +351,7 @@ class CreatePost extends React.Component { return; } - if (!e.ctrlKey && !e.metaKey && e.keyCode === KeyCodes.UP && this.state.messageText === '') { + if (!e.ctrlKey && !e.metaKey && !e.altKey && !e.shiftKey && e.keyCode === KeyCodes.UP && this.state.messageText === '') { e.preventDefault(); const channelId = ChannelStore.getCurrentId(); @@ -373,7 +373,7 @@ class CreatePost extends React.Component { }); } - if ((e.ctrlKey || e.metaKey) && e.keyCode === KeyCodes.UP) { + if ((e.ctrlKey || e.metaKey) && !e.altKey && !e.shiftKey && e.keyCode === KeyCodes.UP) { const channelId = ChannelStore.getCurrentId(); const lastPost = PostStore.getCurrentUsersLatestPost(channelId); if (!lastPost) { diff --git a/webapp/components/navbar.jsx b/webapp/components/navbar.jsx index ee199fc03..ea5d99603 100644 --- a/webapp/components/navbar.jsx +++ b/webapp/components/navbar.jsx @@ -34,6 +34,8 @@ 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); @@ -50,6 +52,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.compareByDmName = this.compareByDmName.bind(this); + const state = this.getStateFromStores(); state.showEditChannelPurposeModal = false; state.showEditChannelHeaderModal = false; @@ -72,10 +80,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 +162,73 @@ 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 = 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 = ( -- cgit v1.2.3-1-g7c22