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
Этот коммит содержится в:
коммит произвёл
Corey Hulen
родитель
1b9deb4392
Коммит
2ccf5bbaa2
@@ -205,7 +205,7 @@ class CreateComment extends React.Component {
|
|||||||
return;
|
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();
|
e.preventDefault();
|
||||||
|
|
||||||
const lastPost = PostStore.getCurrentUsersLatestPost(this.props.channelId, this.props.rootId);
|
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);
|
const lastPost = PostStore.getCurrentUsersLatestPost(this.props.channelId, this.props.rootId);
|
||||||
if (!lastPost) {
|
if (!lastPost) {
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -351,7 +351,7 @@ class CreatePost extends React.Component {
|
|||||||
return;
|
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();
|
e.preventDefault();
|
||||||
|
|
||||||
const channelId = ChannelStore.getCurrentId();
|
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 channelId = ChannelStore.getCurrentId();
|
||||||
const lastPost = PostStore.getCurrentUsersLatestPost(channelId);
|
const lastPost = PostStore.getCurrentUsersLatestPost(channelId);
|
||||||
if (!lastPost) {
|
if (!lastPost) {
|
||||||
|
|||||||
@@ -34,6 +34,8 @@ import {Link, browserHistory} from 'react-router';
|
|||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
|
import * as GlobalActions from 'action_creators/global_actions.jsx';
|
||||||
|
|
||||||
export default class Navbar extends React.Component {
|
export default class Navbar extends React.Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
@@ -50,6 +52,12 @@ export default class Navbar extends React.Component {
|
|||||||
this.createCollapseButtons = this.createCollapseButtons.bind(this);
|
this.createCollapseButtons = this.createCollapseButtons.bind(this);
|
||||||
this.createDropdown = this.createDropdown.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();
|
const state = this.getStateFromStores();
|
||||||
state.showEditChannelPurposeModal = false;
|
state.showEditChannelPurposeModal = false;
|
||||||
state.showEditChannelHeaderModal = false;
|
state.showEditChannelHeaderModal = false;
|
||||||
@@ -72,10 +80,14 @@ export default class Navbar extends React.Component {
|
|||||||
ChannelStore.addChangeListener(this.onChange);
|
ChannelStore.addChangeListener(this.onChange);
|
||||||
ChannelStore.addExtraInfoChangeListener(this.onChange);
|
ChannelStore.addExtraInfoChangeListener(this.onChange);
|
||||||
$('.inner-wrap').click(this.hideSidebars);
|
$('.inner-wrap').click(this.hideSidebars);
|
||||||
|
document.addEventListener('keydown', this.navigateChannelShortcut);
|
||||||
|
document.addEventListener('keydown', this.navigateUnreadChannelShortcut);
|
||||||
}
|
}
|
||||||
componentWillUnmount() {
|
componentWillUnmount() {
|
||||||
ChannelStore.removeChangeListener(this.onChange);
|
ChannelStore.removeChangeListener(this.onChange);
|
||||||
ChannelStore.removeExtraInfoChangeListener(this.onChange);
|
ChannelStore.removeExtraInfoChangeListener(this.onChange);
|
||||||
|
document.removeEventListener('keydown', this.navigateChannelShortcut);
|
||||||
|
document.removeEventListener('keydown', this.navigateUnreadChannelShortcut);
|
||||||
}
|
}
|
||||||
handleSubmit(e) {
|
handleSubmit(e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
@@ -150,6 +162,73 @@ export default class Navbar extends React.Component {
|
|||||||
showRenameChannelModal: false
|
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) {
|
createDropdown(channel, channelTitle, isAdmin, isDirect, popoverContent) {
|
||||||
if (channel) {
|
if (channel) {
|
||||||
var viewInfoOption = (
|
var viewInfoOption = (
|
||||||
|
|||||||
Ссылка в новой задаче
Block a user