mirror of
https://github.com/mattermost/mattermost.git
synced 2025-02-25 18:55:24 -06:00
Moved unread channel indicators into their own React component and file
This commit is contained in:
@@ -11,6 +11,7 @@ var BrowserStore = require('../stores/browser_store.jsx');
|
||||
var Utils = require('../utils/utils.jsx');
|
||||
var SidebarHeader = require('./sidebar_header.jsx');
|
||||
var SearchBox = require('./search_bar.jsx');
|
||||
var UnreadChannelIndicators = require('./unread_channel_indicators.jsx');
|
||||
var Constants = require('../utils/constants.jsx');
|
||||
var NewChannelFlow = require('./new_channel_flow.jsx');
|
||||
|
||||
@@ -19,13 +20,10 @@ export default class Sidebar extends React.Component {
|
||||
super(props);
|
||||
|
||||
this.badgesActive = false;
|
||||
this.firstUnreadChannel = null;
|
||||
this.lastUnreadChannel = null;
|
||||
|
||||
this.onChange = this.onChange.bind(this);
|
||||
this.onScroll = this.onScroll.bind(this);
|
||||
this.onResize = this.onResize.bind(this);
|
||||
this.updateUnreadIndicators = this.updateUnreadIndicators.bind(this);
|
||||
this.createChannelElement = this.createChannelElement.bind(this);
|
||||
|
||||
this.state = this.getStateFromStores();
|
||||
@@ -149,13 +147,13 @@ export default class Sidebar extends React.Component {
|
||||
$('.nav-pills__container').perfectScrollbar();
|
||||
|
||||
this.updateTitle();
|
||||
this.updateUnreadIndicators();
|
||||
this.refs.unreadIndicators.onParentUpdate(this.refs);
|
||||
|
||||
$(window).on('resize', this.onResize);
|
||||
}
|
||||
componentDidUpdate() {
|
||||
this.updateTitle();
|
||||
this.updateUnreadIndicators();
|
||||
this.refs.unreadIndicators.onParentUpdate(this.refs);
|
||||
}
|
||||
componentWillUnmount() {
|
||||
$(window).off('resize', this.onResize);
|
||||
@@ -268,41 +266,12 @@ export default class Sidebar extends React.Component {
|
||||
}
|
||||
}
|
||||
onScroll() {
|
||||
this.updateUnreadIndicators();
|
||||
this.refs.unreadIndicators.onParentUpdate(this.refs);
|
||||
}
|
||||
onResize() {
|
||||
this.updateUnreadIndicators();
|
||||
this.refs.unreadIndicators.onParentUpdate(this.refs);
|
||||
}
|
||||
updateUnreadIndicators() {
|
||||
const container = $(React.findDOMNode(this.refs.container));
|
||||
const topUnreadIndicator = $(React.findDOMNode(this.refs.topUnreadIndicator));
|
||||
const bottomUnreadIndicator = $(React.findDOMNode(this.refs.bottomUnreadIndicator));
|
||||
|
||||
if (this.firstUnreadChannel) {
|
||||
var firstUnreadElement = $(React.findDOMNode(this.refs[this.firstUnreadChannel]));
|
||||
|
||||
if (firstUnreadElement.position().top + firstUnreadElement.height() < 0) {
|
||||
topUnreadIndicator.css('display', 'initial');
|
||||
} else {
|
||||
topUnreadIndicator.css('display', 'none');
|
||||
}
|
||||
} else {
|
||||
topUnreadIndicator.css('display', 'none');
|
||||
}
|
||||
|
||||
if (this.lastUnreadChannel) {
|
||||
var lastUnreadElement = $(React.findDOMNode(this.refs[this.lastUnreadChannel]));
|
||||
|
||||
if (lastUnreadElement.position().top > container.height()) {
|
||||
bottomUnreadIndicator.css('display', 'initial');
|
||||
} else {
|
||||
bottomUnreadIndicator.css('display', 'none');
|
||||
}
|
||||
} else {
|
||||
bottomUnreadIndicator.css('display', 'none');
|
||||
}
|
||||
}
|
||||
createChannelElement(channel, index) {
|
||||
createChannelElement(unreadChannels, channel, index) {
|
||||
var members = this.state.members;
|
||||
var activeId = this.state.activeId;
|
||||
var channelMember = members[channel.id];
|
||||
@@ -324,10 +293,7 @@ export default class Sidebar extends React.Component {
|
||||
titleClass = 'unread-title';
|
||||
|
||||
if (channel.id !== activeId) {
|
||||
if (!this.firstUnreadChannel) {
|
||||
this.firstUnreadChannel = channel.name;
|
||||
}
|
||||
this.lastUnreadChannel = channel.name;
|
||||
unreadChannels.push(channel);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -433,24 +399,17 @@ export default class Sidebar extends React.Component {
|
||||
render() {
|
||||
this.badgesActive = false;
|
||||
|
||||
// keep track of the first and last unread channels so we can use them to set the unread indicators
|
||||
this.firstUnreadChannel = null;
|
||||
this.lastUnreadChannel = null;
|
||||
// keep track of unread channels so we can use them to set the unread indicators
|
||||
const unreadChannels = [];
|
||||
|
||||
// create elements for all 3 types of channels
|
||||
var channelItems = this.state.channels.filter(
|
||||
function filterPublicChannels(channel) {
|
||||
return channel.type === 'O';
|
||||
}
|
||||
).map(this.createChannelElement);
|
||||
const publicChannels = this.state.channels.filter((channel) => channel.type === 'O');
|
||||
const publicChannelItems = publicChannels.map(this.createChannelElement.bind(this, unreadChannels));
|
||||
|
||||
var privateChannelItems = this.state.channels.filter(
|
||||
function filterPrivateChannels(channel) {
|
||||
return channel.type === 'P';
|
||||
}
|
||||
).map(this.createChannelElement);
|
||||
const privateChannels = this.state.channels.filter((channel) => channel.type === 'P');
|
||||
const privateChannelItems = privateChannels.map(this.createChannelElement.bind(this, unreadChannels));
|
||||
|
||||
var directMessageItems = this.state.showDirectChannels.map(this.createChannelElement);
|
||||
const directMessageItems = this.state.showDirectChannels.map(this.createChannelElement.bind(this, unreadChannels));
|
||||
|
||||
// update the favicon to show if there are any notifications
|
||||
var link = document.createElement('link');
|
||||
@@ -504,20 +463,10 @@ export default class Sidebar extends React.Component {
|
||||
/>
|
||||
<SearchBox />
|
||||
|
||||
<div
|
||||
ref='topUnreadIndicator'
|
||||
className='nav-pills__unread-indicator nav-pills__unread-indicator-top'
|
||||
style={{display: 'none'}}
|
||||
>
|
||||
Unread post(s) above
|
||||
</div>
|
||||
<div
|
||||
ref='bottomUnreadIndicator'
|
||||
className='nav-pills__unread-indicator nav-pills__unread-indicator-bottom'
|
||||
style={{display: 'none'}}
|
||||
>
|
||||
Unread post(s) below
|
||||
</div>
|
||||
<UnreadChannelIndicators
|
||||
ref='unreadIndicators'
|
||||
unreadChannels={unreadChannels}
|
||||
/>
|
||||
|
||||
<div
|
||||
ref='container'
|
||||
@@ -537,7 +486,7 @@ export default class Sidebar extends React.Component {
|
||||
</a>
|
||||
</h4>
|
||||
</li>
|
||||
{channelItems}
|
||||
{publicChannelItems}
|
||||
<li>
|
||||
<a
|
||||
href='#'
|
||||
|
||||
93
web/react/components/unread_channel_indicators.jsx
Normal file
93
web/react/components/unread_channel_indicators.jsx
Normal file
@@ -0,0 +1,93 @@
|
||||
// Copyright (c) 2015 Spinpunch, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
// Indicators for the left sidebar which indicate if there's unread posts in a channel that is not shown
|
||||
// because it is either above or below the screen
|
||||
export default class UnreadChannelIndicators extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.getFirstLastUnreadChannels = this.getFirstLastUnreadChannels.bind(this);
|
||||
this.onParentUpdate = this.onParentUpdate.bind(this);
|
||||
|
||||
this.state = this.getFirstLastUnreadChannels(props);
|
||||
}
|
||||
|
||||
getFirstLastUnreadChannels(props) {
|
||||
let firstUnreadChannel = null;
|
||||
let lastUnreadChannel = null;
|
||||
|
||||
for (const unreadChannel of props.unreadChannels) {
|
||||
if (!firstUnreadChannel) {
|
||||
firstUnreadChannel = unreadChannel;
|
||||
}
|
||||
lastUnreadChannel = unreadChannel;
|
||||
}
|
||||
|
||||
return {
|
||||
firstUnreadChannel,
|
||||
lastUnreadChannel
|
||||
};
|
||||
}
|
||||
|
||||
onParentUpdate(parentRefs) {
|
||||
const container = $(React.findDOMNode(parentRefs.container));
|
||||
const topUnreadIndicator = $(React.findDOMNode(this.refs.topIndicator));
|
||||
const bottomUnreadIndicator = $(React.findDOMNode(this.refs.bottomIndicator));
|
||||
|
||||
if (this.state.firstUnreadChannel) {
|
||||
var firstUnreadElement = $(React.findDOMNode(parentRefs[this.state.firstUnreadChannel.name]));
|
||||
|
||||
if (firstUnreadElement.position().top + firstUnreadElement.height() < 0) {
|
||||
topUnreadIndicator.css('display', 'initial');
|
||||
} else {
|
||||
topUnreadIndicator.css('display', 'none');
|
||||
}
|
||||
} else {
|
||||
topUnreadIndicator.css('display', 'none');
|
||||
}
|
||||
|
||||
if (this.state.lastUnreadChannel) {
|
||||
var lastUnreadElement = $(React.findDOMNode(parentRefs[this.state.lastUnreadChannel.name]));
|
||||
|
||||
if (lastUnreadElement.position().top > container.height()) {
|
||||
bottomUnreadIndicator.css('display', 'initial');
|
||||
} else {
|
||||
bottomUnreadIndicator.css('display', 'none');
|
||||
}
|
||||
} else {
|
||||
bottomUnreadIndicator.css('display', 'none');
|
||||
}
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
this.setState(this.getFirstLastUnreadChannels(nextProps));
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
<div
|
||||
ref='topIndicator'
|
||||
className='nav-pills__unread-indicator nav-pills__unread-indicator-top'
|
||||
style={{display: 'none'}}
|
||||
>
|
||||
{'Unread post(s) above'}
|
||||
</div>
|
||||
<div
|
||||
ref='bottomIndicator'
|
||||
className='nav-pills__unread-indicator nav-pills__unread-indicator-bottom'
|
||||
style={{display: 'none'}}
|
||||
>
|
||||
{'Unread post(s) below'}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
UnreadChannelIndicators.propTypes = {
|
||||
|
||||
// a list of the unread channels displayed in the parent
|
||||
unreadChannels: React.PropTypes.array.isRequired
|
||||
};
|
||||
Reference in New Issue
Block a user