Moved unread channel indicators into their own React component and file

Этот коммит содержится в:
hmhealey
2015-09-15 17:36:48 -04:00
родитель 8d0c69aec6
Коммит 7e66a3d5be
2 изменённых файлов: 112 добавлений и 70 удалений

Просмотреть файл

@@ -11,6 +11,7 @@ var BrowserStore = require('../stores/browser_store.jsx');
var Utils = require('../utils/utils.jsx'); var Utils = require('../utils/utils.jsx');
var SidebarHeader = require('./sidebar_header.jsx'); var SidebarHeader = require('./sidebar_header.jsx');
var SearchBox = require('./search_bar.jsx'); var SearchBox = require('./search_bar.jsx');
var UnreadChannelIndicators = require('./unread_channel_indicators.jsx');
var Constants = require('../utils/constants.jsx'); var Constants = require('../utils/constants.jsx');
var NewChannelFlow = require('./new_channel_flow.jsx'); var NewChannelFlow = require('./new_channel_flow.jsx');
@@ -19,13 +20,10 @@ export default class Sidebar extends React.Component {
super(props); super(props);
this.badgesActive = false; this.badgesActive = false;
this.firstUnreadChannel = null;
this.lastUnreadChannel = null;
this.onChange = this.onChange.bind(this); this.onChange = this.onChange.bind(this);
this.onScroll = this.onScroll.bind(this); this.onScroll = this.onScroll.bind(this);
this.onResize = this.onResize.bind(this); this.onResize = this.onResize.bind(this);
this.updateUnreadIndicators = this.updateUnreadIndicators.bind(this);
this.createChannelElement = this.createChannelElement.bind(this); this.createChannelElement = this.createChannelElement.bind(this);
this.state = this.getStateFromStores(); this.state = this.getStateFromStores();
@@ -149,13 +147,13 @@ export default class Sidebar extends React.Component {
$('.nav-pills__container').perfectScrollbar(); $('.nav-pills__container').perfectScrollbar();
this.updateTitle(); this.updateTitle();
this.updateUnreadIndicators(); this.refs.unreadIndicators.onParentUpdate(this.refs);
$(window).on('resize', this.onResize); $(window).on('resize', this.onResize);
} }
componentDidUpdate() { componentDidUpdate() {
this.updateTitle(); this.updateTitle();
this.updateUnreadIndicators(); this.refs.unreadIndicators.onParentUpdate(this.refs);
} }
componentWillUnmount() { componentWillUnmount() {
$(window).off('resize', this.onResize); $(window).off('resize', this.onResize);
@@ -268,41 +266,12 @@ export default class Sidebar extends React.Component {
} }
} }
onScroll() { onScroll() {
this.updateUnreadIndicators(); this.refs.unreadIndicators.onParentUpdate(this.refs);
} }
onResize() { onResize() {
this.updateUnreadIndicators(); this.refs.unreadIndicators.onParentUpdate(this.refs);
} }
updateUnreadIndicators() { createChannelElement(unreadChannels, channel, index) {
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) {
var members = this.state.members; var members = this.state.members;
var activeId = this.state.activeId; var activeId = this.state.activeId;
var channelMember = members[channel.id]; var channelMember = members[channel.id];
@@ -324,10 +293,7 @@ export default class Sidebar extends React.Component {
titleClass = 'unread-title'; titleClass = 'unread-title';
if (channel.id !== activeId) { if (channel.id !== activeId) {
if (!this.firstUnreadChannel) { unreadChannels.push(channel);
this.firstUnreadChannel = channel.name;
}
this.lastUnreadChannel = channel.name;
} }
} }
@@ -433,24 +399,17 @@ export default class Sidebar extends React.Component {
render() { render() {
this.badgesActive = false; this.badgesActive = false;
// keep track of the first and last unread channels so we can use them to set the unread indicators // keep track of unread channels so we can use them to set the unread indicators
this.firstUnreadChannel = null; const unreadChannels = [];
this.lastUnreadChannel = null;
// create elements for all 3 types of channels // create elements for all 3 types of channels
var channelItems = this.state.channels.filter( const publicChannels = this.state.channels.filter((channel) => channel.type === 'O');
function filterPublicChannels(channel) { const publicChannelItems = publicChannels.map(this.createChannelElement.bind(this, unreadChannels));
return channel.type === 'O';
}
).map(this.createChannelElement);
var privateChannelItems = this.state.channels.filter( const privateChannels = this.state.channels.filter((channel) => channel.type === 'P');
function filterPrivateChannels(channel) { const privateChannelItems = privateChannels.map(this.createChannelElement.bind(this, unreadChannels));
return channel.type === 'P';
}
).map(this.createChannelElement);
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 // update the favicon to show if there are any notifications
var link = document.createElement('link'); var link = document.createElement('link');
@@ -504,20 +463,10 @@ export default class Sidebar extends React.Component {
/> />
<SearchBox /> <SearchBox />
<div <UnreadChannelIndicators
ref='topUnreadIndicator' ref='unreadIndicators'
className='nav-pills__unread-indicator nav-pills__unread-indicator-top' unreadChannels={unreadChannels}
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>
<div <div
ref='container' ref='container'
@@ -537,7 +486,7 @@ export default class Sidebar extends React.Component {
</a> </a>
</h4> </h4>
</li> </li>
{channelItems} {publicChannelItems}
<li> <li>
<a <a
href='#' href='#'

Просмотреть файл

@@ -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
};