Cleaned up logic for the unread indicators
Этот коммит содержится в:
коммит произвёл
hmhealey
родитель
7e66a3d5be
Коммит
acf2fb64b4
@@ -11,19 +11,22 @@ 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');
|
||||||
|
var UnreadChannelIndicator = require('./unread_channel_indicator.jsx');
|
||||||
|
|
||||||
export default class Sidebar extends React.Component {
|
export default class Sidebar extends React.Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
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();
|
||||||
@@ -147,13 +150,23 @@ export default class Sidebar extends React.Component {
|
|||||||
$('.nav-pills__container').perfectScrollbar();
|
$('.nav-pills__container').perfectScrollbar();
|
||||||
|
|
||||||
this.updateTitle();
|
this.updateTitle();
|
||||||
this.refs.unreadIndicators.onParentUpdate(this.refs);
|
this.updateUnreadIndicators();
|
||||||
|
|
||||||
$(window).on('resize', this.onResize);
|
$(window).on('resize', this.onResize);
|
||||||
}
|
}
|
||||||
|
shouldComponentUpdate(nextProps, nextState) {
|
||||||
|
if (!Utils.areStatesEqual(nextProps, this.props)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Utils.areStatesEqual(nextState, this.state)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
componentDidUpdate() {
|
componentDidUpdate() {
|
||||||
this.updateTitle();
|
this.updateTitle();
|
||||||
this.refs.unreadIndicators.onParentUpdate(this.refs);
|
this.updateUnreadIndicators();
|
||||||
}
|
}
|
||||||
componentWillUnmount() {
|
componentWillUnmount() {
|
||||||
$(window).off('resize', this.onResize);
|
$(window).off('resize', this.onResize);
|
||||||
@@ -266,12 +279,39 @@ export default class Sidebar extends React.Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
onScroll() {
|
onScroll() {
|
||||||
this.refs.unreadIndicators.onParentUpdate(this.refs);
|
this.updateUnreadIndicators();
|
||||||
}
|
}
|
||||||
onResize() {
|
onResize() {
|
||||||
this.refs.unreadIndicators.onParentUpdate(this.refs);
|
this.updateUnreadIndicators();
|
||||||
}
|
}
|
||||||
createChannelElement(unreadChannels, channel, index) {
|
updateUnreadIndicators() {
|
||||||
|
const container = $(React.findDOMNode(this.refs.container));
|
||||||
|
|
||||||
|
var showTopUnread = false;
|
||||||
|
var showBottomUnread = false;
|
||||||
|
|
||||||
|
if (this.firstUnreadChannel) {
|
||||||
|
var firstUnreadElement = $(React.findDOMNode(this.refs[this.firstUnreadChannel]));
|
||||||
|
|
||||||
|
if (firstUnreadElement.position().top + firstUnreadElement.height() < 0) {
|
||||||
|
showTopUnread = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.lastUnreadChannel) {
|
||||||
|
var lastUnreadElement = $(React.findDOMNode(this.refs[this.lastUnreadChannel]));
|
||||||
|
|
||||||
|
if (lastUnreadElement.position().top > container.height()) {
|
||||||
|
showBottomUnread = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.setState({
|
||||||
|
showTopUnread,
|
||||||
|
showBottomUnread
|
||||||
|
});
|
||||||
|
}
|
||||||
|
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];
|
||||||
@@ -293,7 +333,10 @@ export default class Sidebar extends React.Component {
|
|||||||
titleClass = 'unread-title';
|
titleClass = 'unread-title';
|
||||||
|
|
||||||
if (channel.id !== activeId) {
|
if (channel.id !== activeId) {
|
||||||
unreadChannels.push(channel);
|
if (!this.firstUnreadChannel) {
|
||||||
|
this.firstUnreadChannel = channel.name;
|
||||||
|
}
|
||||||
|
this.lastUnreadChannel = channel.name;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -399,17 +442,18 @@ export default class Sidebar extends React.Component {
|
|||||||
render() {
|
render() {
|
||||||
this.badgesActive = false;
|
this.badgesActive = false;
|
||||||
|
|
||||||
// keep track of unread channels so we can use them to set the unread indicators
|
// keep track of the first and last unread channels so we can use them to set the unread indicators
|
||||||
const unreadChannels = [];
|
this.firstUnreadChannel = null;
|
||||||
|
this.lastUnreadChannel = null;
|
||||||
|
|
||||||
// create elements for all 3 types of channels
|
// create elements for all 3 types of channels
|
||||||
const publicChannels = this.state.channels.filter((channel) => channel.type === 'O');
|
const publicChannels = this.state.channels.filter((channel) => channel.type === 'O');
|
||||||
const publicChannelItems = publicChannels.map(this.createChannelElement.bind(this, unreadChannels));
|
const publicChannelItems = publicChannels.map(this.createChannelElement);
|
||||||
|
|
||||||
const privateChannels = this.state.channels.filter((channel) => channel.type === 'P');
|
const privateChannels = this.state.channels.filter((channel) => channel.type === 'P');
|
||||||
const privateChannelItems = privateChannels.map(this.createChannelElement.bind(this, unreadChannels));
|
const privateChannelItems = privateChannels.map(this.createChannelElement);
|
||||||
|
|
||||||
const directMessageItems = this.state.showDirectChannels.map(this.createChannelElement.bind(this, unreadChannels));
|
const directMessageItems = this.state.showDirectChannels.map(this.createChannelElement);
|
||||||
|
|
||||||
// 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');
|
||||||
@@ -463,9 +507,15 @@ export default class Sidebar extends React.Component {
|
|||||||
/>
|
/>
|
||||||
<SearchBox />
|
<SearchBox />
|
||||||
|
|
||||||
<UnreadChannelIndicators
|
<UnreadChannelIndicator
|
||||||
ref='unreadIndicators'
|
show={this.state.showTopUnread}
|
||||||
unreadChannels={unreadChannels}
|
extraClass='nav-pills__unread-indicator-top'
|
||||||
|
text={'Unread post(s) above'}
|
||||||
|
/>
|
||||||
|
<UnreadChannelIndicator
|
||||||
|
show={this.state.showBottomUnread}
|
||||||
|
extraClass='nav-pills__unread-indicator-bottom'
|
||||||
|
text={'Unread post(s) below'}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
|
|||||||
35
web/react/components/unread_channel_indicator.jsx
Обычный файл
35
web/react/components/unread_channel_indicator.jsx
Обычный файл
@@ -0,0 +1,35 @@
|
|||||||
|
// Copyright (c) 2015 Spinpunch, Inc. All Rights Reserved.
|
||||||
|
// See License.txt for license information.
|
||||||
|
|
||||||
|
// Indicator 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 UnreadChannelIndicator extends React.Component {
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
}
|
||||||
|
render() {
|
||||||
|
let displayValue = 'none';
|
||||||
|
if (this.props.show) {
|
||||||
|
displayValue = 'initial';
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className={'nav-pills__unread-indicator ' + this.props.extraClass}
|
||||||
|
style={{display: displayValue}}
|
||||||
|
>
|
||||||
|
{this.props.text}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
UnreadChannelIndicator.defaultProps = {
|
||||||
|
show: false,
|
||||||
|
extraClass: '',
|
||||||
|
text: ''
|
||||||
|
};
|
||||||
|
UnreadChannelIndicator.propTypes = {
|
||||||
|
show: React.PropTypes.bool,
|
||||||
|
extraClass: React.PropTypes.string,
|
||||||
|
text: React.PropTypes.string
|
||||||
|
};
|
||||||
@@ -1,93 +0,0 @@
|
|||||||
// 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
|
|
||||||
};
|
|
||||||
Ссылка в новой задаче
Block a user