From 4b0636217232817351985ba9ee8033c03c4e8480 Mon Sep 17 00:00:00 2001 From: David Lu Date: Wed, 1 Jun 2016 13:05:48 -0700 Subject: Added scrolling, move out of navbar (#3163) Added magic number, removed jqueryi --- webapp/components/navbar.jsx | 99 ------------------------------------------- webapp/components/sidebar.jsx | 79 +++++++++++++++++++++++++++++++++- webapp/utils/constants.jsx | 1 + 3 files changed, 79 insertions(+), 100 deletions(-) (limited to 'webapp') diff --git a/webapp/components/navbar.jsx b/webapp/components/navbar.jsx index 93f800814..ee199fc03 100644 --- a/webapp/components/navbar.jsx +++ b/webapp/components/navbar.jsx @@ -17,7 +17,6 @@ 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'; @@ -35,8 +34,6 @@ import {Link, browserHistory} from 'react-router'; import React from 'react'; -import * as ChannelActions from 'actions/channel_actions.jsx'; - export default class Navbar extends React.Component { constructor(props) { super(props); @@ -53,11 +50,6 @@ 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.compareByDisplayName = this.compareByDisplayName.bind(this); - const state = this.getStateFromStores(); state.showEditChannelPurposeModal = false; state.showEditChannelHeaderModal = false; @@ -80,14 +72,10 @@ 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(); @@ -162,93 +150,6 @@ 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)]; - ChannelActions.goToChannel(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]; - ChannelActions.goToChannel(nextChannel); - } - } - } - getDisplayedChannels() { - const allChannels = ChannelStore.getChannels().sort(this.compareByDisplayName); - 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); - } - compareByDisplayName(channelA, channelB) { - return channelA.display_name.localeCompare(channelB.display_name); - } createDropdown(channel, channelTitle, isAdmin, isDirect, popoverContent) { if (channel) { var viewInfoOption = ( diff --git a/webapp/components/sidebar.jsx b/webapp/components/sidebar.jsx index 28b22fc81..8abf3fa55 100644 --- a/webapp/components/sidebar.jsx +++ b/webapp/components/sidebar.jsx @@ -16,6 +16,7 @@ import PreferenceStore from 'stores/preference_store.jsx'; import * as AsyncClient from 'utils/async_client.jsx'; import * as Utils from 'utils/utils.jsx'; +import * as ChannelActions from 'actions/channel_actions.jsx'; import Constants from 'utils/constants.jsx'; @@ -57,6 +58,11 @@ export default class Sidebar extends React.Component { this.createChannelElement = this.createChannelElement.bind(this); this.updateTitle = this.updateTitle.bind(this); + this.navigateChannelShortcut = this.navigateChannelShortcut.bind(this); + this.navigateUnreadChannelShortcut = this.navigateUnreadChannelShortcut.bind(this); + this.getDisplayedChannels = this.getDisplayedChannels.bind(this); + this.updateScrollbarOnChannelChange = this.updateScrollbarOnChannelChange.bind(this); + this.isLeaving = new Map(); const state = this.getStateFromStores(); @@ -155,6 +161,9 @@ export default class Sidebar extends React.Component { this.updateTitle(); this.updateUnreadIndicators(); + + document.addEventListener('keydown', this.navigateChannelShortcut); + document.addEventListener('keydown', this.navigateUnreadChannelShortcut); } shouldComponentUpdate(nextProps, nextState) { if (!Utils.areObjectsEqual(nextState, this.state)) { @@ -187,6 +196,8 @@ export default class Sidebar extends React.Component { UserStore.removeStatusesChangeListener(this.onChange); TeamStore.removeChangeListener(this.onChange); PreferenceStore.removeChangeListener(this.onChange); + document.removeEventListener('keydown', this.navigateChannelShortcut); + document.removeEventListener('keydown', this.navigateUnreadChannelShortcut); } onChange() { this.setState(this.getStateFromStores()); @@ -243,7 +254,73 @@ export default class Sidebar extends React.Component { showBottomUnread }); } - + updateScrollbarOnChannelChange(channel) { + const curChannel = this.refs[channel.name].getBoundingClientRect(); + if ((curChannel.top - Constants.CHANNEL_SCROLL_ADJUSTMENT < 0) || (curChannel.top + curChannel.height > this.refs.container.getBoundingClientRect().height)) { + this.refs.container.scrollTop = this.refs.container.scrollTop + (curChannel.top - Constants.CHANNEL_SCROLL_ADJUSTMENT); + $('.nav-pills__container').perfectScrollbar('update'); + } + } + navigateChannelShortcut(e) { + if (e.altKey && !e.shiftKey && (e.keyCode === Constants.KeyCodes.UP || e.keyCode === Constants.KeyCodes.DOWN)) { + e.preventDefault(); + const allChannels = this.getDisplayedChannels(); + const curChannelId = this.state.activeId; + let curIndex = -1; + for (let i = 0; i < allChannels.length; i++) { + if (allChannels[i].id === curChannelId) { + curIndex = i; + } + } + let nextChannel = allChannels[curIndex]; + 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)]; + ChannelActions.goToChannel(nextChannel); + this.updateScrollbarOnChannelChange(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 curChannelId = this.state.activeId; + let curIndex = -1; + for (let i = 0; i < allChannels.length; i++) { + if (allChannels[i].id === curChannelId) { + curIndex = i; + } + } + let nextChannel = allChannels[curIndex]; + 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]; + ChannelActions.goToChannel(nextChannel); + this.updateScrollbarOnChannelChange(nextChannel); + } + } + } + getDisplayedChannels() { + return this.state.publicChannels.concat(this.state.privateChannels).concat(this.state.directChannels).concat(this.state.directNonTeamChannels); + } handleLeaveDirectChannel(e, channel) { e.preventDefault(); diff --git a/webapp/utils/constants.jsx b/webapp/utils/constants.jsx index 1281e320f..55090fc82 100644 --- a/webapp/utils/constants.jsx +++ b/webapp/utils/constants.jsx @@ -746,6 +746,7 @@ export default { MAX_TRIGGER_LENGTH: 128, TIME_SINCE_UPDATE_INTERVAL: 30000, MIN_HASHTAG_LINK_LENGTH: 3, + CHANNEL_SCROLL_ADJUSTMENT: 100, EMOJI_PATH: '/static/emoji', DEFAULT_WEBHOOK_LOGO: logoWebhook, MHPNS: 'https://push.mattermost.com', -- cgit v1.2.3-1-g7c22