Add post list container to hold mounted post lists for faster rendering/channel switching.

Этот коммит содержится в:
JoramWilander
2015-09-08 10:11:57 -04:00
родитель 5b3ee66dc3
Коммит 5c0680397d
8 изменённых файлов: 251 добавлений и 107 удалений

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

@@ -64,9 +64,14 @@ export default class ChannelHeader extends React.Component {
handleLeave() { handleLeave() {
Client.leaveChannel(this.state.channel.id, Client.leaveChannel(this.state.channel.id,
function handleLeaveSuccess() { function handleLeaveSuccess() {
AppDispatcher.handleViewAction({
type: ActionTypes.LEAVE_CHANNEL,
id: this.state.channel.id
});
const townsquare = ChannelStore.getByName('town-square'); const townsquare = ChannelStore.getByName('town-square');
Utils.switchChannel(townsquare); Utils.switchChannel(townsquare);
}, }.bind(this),
function handleLeaveError(err) { function handleLeaveError(err) {
AsyncClient.dispatchError(err, 'handleLeave'); AsyncClient.dispatchError(err, 'handleLeave');
} }

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

@@ -17,6 +17,8 @@ export default class ChannelLoader extends React.Component {
constructor(props) { constructor(props) {
super(props); super(props);
this.intervalId = null;
this.onSocketChange = this.onSocketChange.bind(this); this.onSocketChange = this.onSocketChange.bind(this);
this.state = {}; this.state = {};
@@ -35,10 +37,12 @@ export default class ChannelLoader extends React.Component {
PostStore.clearPendingPosts(); PostStore.clearPendingPosts();
/* Set up interval functions */ /* Set up interval functions */
setInterval( this.intervalId = setInterval(
function pollStatuses() { function pollStatuses() {
AsyncClient.getStatuses(); AsyncClient.getStatuses();
}, 30000); },
30000
);
/* Device tracking setup */ /* Device tracking setup */
var iOS = (/(iPad|iPhone|iPod)/g).test(navigator.userAgent); var iOS = (/(iPad|iPhone|iPod)/g).test(navigator.userAgent);
@@ -49,12 +53,12 @@ export default class ChannelLoader extends React.Component {
/* Set up tracking for whether the window is active */ /* Set up tracking for whether the window is active */
window.isActive = true; window.isActive = true;
$(window).focus(function windowFocus() { $(window).on('focus', function windowFocus() {
AsyncClient.updateLastViewedAt(); AsyncClient.updateLastViewedAt();
window.isActive = true; window.isActive = true;
}); });
$(window).blur(function windowBlur() { $(window).on('blur', function windowBlur() {
window.isActive = false; window.isActive = false;
}); });
@@ -84,6 +88,54 @@ export default class ChannelLoader extends React.Component {
Utils.changeCss('.btn.btn-primary:hover, .btn.btn-primary:active, .btn.btn-primary:focus', 'background: ' + Utils.changeColor(user.props.theme, +10) + ';'); Utils.changeCss('.btn.btn-primary:hover, .btn.btn-primary:active, .btn.btn-primary:focus', 'background: ' + Utils.changeColor(user.props.theme, +10) + ';');
$('.team__header').addClass('theme--gray'); $('.team__header').addClass('theme--gray');
} }
/* Setup global mouse events */
$('body').on('click.userpopover', function popOver(e) {
if ($(e.target).attr('data-toggle') !== 'popover' &&
$(e.target).parents('.popover.in').length === 0) {
$('.user-popover').popover('hide');
}
});
$('body').on('mouseenter mouseleave', '.post', function mouseOver(ev) {
if (ev.type === 'mouseenter') {
$(this).parent('div').prev('.date-separator, .new-separator').addClass('hovered--after');
$(this).parent('div').next('.date-separator, .new-separator').addClass('hovered--before');
} else {
$(this).parent('div').prev('.date-separator, .new-separator').removeClass('hovered--after');
$(this).parent('div').next('.date-separator, .new-separator').removeClass('hovered--before');
}
});
$('body').on('mouseenter mouseleave', '.post.post--comment.same--root', function mouseOver(ev) {
if (ev.type === 'mouseenter') {
$(this).parent('div').prev('.date-separator, .new-separator').addClass('hovered--comment');
$(this).parent('div').next('.date-separator, .new-separator').addClass('hovered--comment');
} else {
$(this).parent('div').prev('.date-separator, .new-separator').removeClass('hovered--comment');
$(this).parent('div').next('.date-separator, .new-separator').removeClass('hovered--comment');
}
});
/* Setup modal events */
$('.modal').on('show.bs.modal', function onShow() {
$('.modal-body').css('overflow-y', 'auto');
$('.modal-body').css('max-height', $(window).height() * 0.7);
});
}
componentWillUnmount() {
clearInterval(this.intervalId);
$(window).off('focus');
$(window).off('blur');
SocketStore.removeChangeListener(this.onSocketChange);
$('body').off('click.userpopover');
$('body').off('mouseenter mouseleave', '.post');
$('body').off('mouseenter mouseleave', '.post.post--comment.same--root');
$('.modal').off('show.bs.modal');
} }
onSocketChange(msg) { onSocketChange(msg) {
if (msg && msg.user_id && msg.user_id !== UserStore.getCurrentId()) { if (msg && msg.user_id && msg.user_id !== UserStore.getCurrentId()) {

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

@@ -18,8 +18,8 @@ var ActionTypes = Constants.ActionTypes;
import {strings} from '../utils/config.js'; import {strings} from '../utils/config.js';
export default class PostList extends React.Component { export default class PostList extends React.Component {
constructor() { constructor(props) {
super(); super(props);
this.gotMorePosts = false; this.gotMorePosts = false;
this.scrolled = false; this.scrolled = false;
@@ -27,6 +27,7 @@ export default class PostList extends React.Component {
this.seenNewMessages = false; this.seenNewMessages = false;
this.isUserScroll = true; this.isUserScroll = true;
this.userHasSeenNew = false; this.userHasSeenNew = false;
this.loadInProgress = false;
this.onChange = this.onChange.bind(this); this.onChange = this.onChange.bind(this);
this.onTimeChange = this.onTimeChange.bind(this); this.onTimeChange = this.onTimeChange.bind(this);
@@ -34,22 +35,19 @@ export default class PostList extends React.Component {
this.createChannelIntroMessage = this.createChannelIntroMessage.bind(this); this.createChannelIntroMessage = this.createChannelIntroMessage.bind(this);
this.loadMorePosts = this.loadMorePosts.bind(this); this.loadMorePosts = this.loadMorePosts.bind(this);
this.loadFirstPosts = this.loadFirstPosts.bind(this); this.loadFirstPosts = this.loadFirstPosts.bind(this);
this.activate = this.activate.bind(this);
this.deactivate = this.deactivate.bind(this);
this.resize = this.resize.bind(this);
this.state = this.getStateFromStores(); this.state = this.getStateFromStores(props.channelId);
this.state.numToDisplay = Constants.POST_CHUNK_SIZE; this.state.numToDisplay = Constants.POST_CHUNK_SIZE;
this.state.isFirstLoadComplete = false; this.state.isFirstLoadComplete = false;
} }
getStateFromStores() { getStateFromStores(id) {
var channel = ChannelStore.getCurrent(); var postList = PostStore.getPosts(id);
if (channel == null) {
channel = {};
}
var postList = PostStore.getCurrentPosts();
if (postList != null) { if (postList != null) {
var deletedPosts = PostStore.getUnseenDeletedPosts(channel.id); var deletedPosts = PostStore.getUnseenDeletedPosts(id);
if (deletedPosts && Object.keys(deletedPosts).length > 0) { if (deletedPosts && Object.keys(deletedPosts).length > 0) {
for (var pid in deletedPosts) { for (var pid in deletedPosts) {
@@ -70,7 +68,7 @@ export default class PostList extends React.Component {
}); });
} }
var pendingPostList = PostStore.getPendingPosts(channel.id); var pendingPostList = PostStore.getPendingPosts(id);
if (pendingPostList) { if (pendingPostList) {
postList.order = pendingPostList.order.concat(postList.order); postList.order = pendingPostList.order.concat(postList.order);
@@ -82,43 +80,42 @@ export default class PostList extends React.Component {
} }
} }
var lastViewed = Number.MAX_VALUE;
if (ChannelStore.getCurrentMember() != null) {
lastViewed = ChannelStore.getCurrentMember().last_viewed_at;
}
return { return {
postList: postList, postList: postList
channel: channel,
lastViewed: lastViewed
}; };
} }
componentDidMount() { componentDidMount() {
if (this.props.isActive) {
this.activate();
this.loadFirstPosts(this.props.channelId);
}
}
componentWillUnmount() {
this.deactivate();
}
activate() {
this.gotMorePosts = false;
this.scrolled = false;
this.prevScrollTop = 0;
this.seenNewMessages = false;
this.isUserScroll = true;
this.userHasSeenNew = false;
PostStore.clearUnseenDeletedPosts(this.props.channelId);
PostStore.addChangeListener(this.onChange); PostStore.addChangeListener(this.onChange);
ChannelStore.addChangeListener(this.onChange);
UserStore.addStatusesChangeListener(this.onTimeChange); UserStore.addStatusesChangeListener(this.onTimeChange);
SocketStore.addChangeListener(this.onSocketChange); SocketStore.addChangeListener(this.onSocketChange);
var postHolder = $('.post-list-holder-by-time'); var postHolder = $(React.findDOMNode(this.refs.postlist));
$('.modal').on('show.bs.modal', function onShow() {
$('.modal-body').css('overflow-y', 'auto');
$('.modal-body').css('max-height', $(window).height() * 0.7);
});
$(window).resize(function resize() {
if ($('#create_post').length > 0) {
var height = $(window).height() - $('#create_post').height() - $('#error_bar').outerHeight() - 50;
postHolder.css('height', height + 'px');
}
$(window).on('resize.' + this.props.channelId, function resize() {
this.resize();
if (!this.scrolled) { if (!this.scrolled) {
this.scrollToBottom(); this.scrollToBottom();
} }
}.bind(this)); }.bind(this));
postHolder.scroll(function scroll() { postHolder.on('scroll', function scroll() {
var position = postHolder.scrollTop() + postHolder.height() + 14; var position = postHolder.scrollTop() + postHolder.height() + 14;
var bottom = postHolder[0].scrollHeight; var bottom = postHolder[0].scrollHeight;
@@ -134,41 +131,25 @@ export default class PostList extends React.Component {
this.isUserScroll = true; this.isUserScroll = true;
}.bind(this)); }.bind(this));
$('body').on('click.userpopover', function popOver(e) {
if ($(e.target).attr('data-toggle') !== 'popover' &&
$(e.target).parents('.popover.in').length === 0) {
$('.user-popover').popover('hide');
}
});
$('.post-list__content div .post').removeClass('post--last'); $('.post-list__content div .post').removeClass('post--last');
$('.post-list__content div:last-child .post').addClass('post--last'); $('.post-list__content div:last-child .post').addClass('post--last');
$('body').on('mouseenter mouseleave', '.post', function mouseOver(ev) { if (!this.state.isFirstLoadComplete) {
if (ev.type === 'mouseenter') { this.loadFirstPosts(this.props.channelId);
$(this).parent('div').prev('.date-separator, .new-separator').addClass('hovered--after');
$(this).parent('div').next('.date-separator, .new-separator').addClass('hovered--before');
} else {
$(this).parent('div').prev('.date-separator, .new-separator').removeClass('hovered--after');
$(this).parent('div').next('.date-separator, .new-separator').removeClass('hovered--before');
}
});
$('body').on('mouseenter mouseleave', '.post.post--comment.same--root', function mouseOver(ev) {
if (ev.type === 'mouseenter') {
$(this).parent('div').prev('.date-separator, .new-separator').addClass('hovered--comment');
$(this).parent('div').next('.date-separator, .new-separator').addClass('hovered--comment');
} else {
$(this).parent('div').prev('.date-separator, .new-separator').removeClass('hovered--comment');
$(this).parent('div').next('.date-separator, .new-separator').removeClass('hovered--comment');
}
});
this.scrollToBottom();
if (this.state.channel.id != null) {
this.loadFirstPosts(this.state.channel.id);
} }
this.resize();
this.onChange();
this.scrollToBottom();
}
deactivate() {
PostStore.removeChangeListener(this.onChange);
UserStore.removeStatusesChangeListener(this.onTimeChange);
SocketStore.removeChangeListener(this.onSocketChange);
$('body').off('click.userpopover');
$(window).off('resize.' + this.props.channelId);
var postHolder = $(React.findDOMNode(this.refs.postlist));
postHolder.off('scroll');
} }
componentDidUpdate(prevProps, prevState) { componentDidUpdate(prevProps, prevState) {
$('.post-list__content div .post').removeClass('post--last'); $('.post-list__content div .post').removeClass('post--last');
@@ -187,7 +168,7 @@ export default class PostList extends React.Component {
var firstPost = posts[order[0]] || {}; var firstPost = posts[order[0]] || {};
var isNewPost = oldOrder.indexOf(order[0]) === -1; var isNewPost = oldOrder.indexOf(order[0]) === -1;
if (this.state.channel.id !== prevState.channel.id) { if (this.props.isActive && !prevProps.isActive) {
this.scrollToBottom(); this.scrollToBottom();
} else if (oldOrder.length === 0) { } else if (oldOrder.length === 0) {
this.scrollToBottom(); this.scrollToBottom();
@@ -201,37 +182,43 @@ export default class PostList extends React.Component {
} else if (isNewPost && } else if (isNewPost &&
userId === firstPost.user_id && userId === firstPost.user_id &&
!utils.isComment(firstPost)) { !utils.isComment(firstPost)) {
this.state.lastViewed = utils.getTimestamp();
this.scrollToBottom(true); this.scrollToBottom(true);
// the user clicked 'load more messages' // the user clicked 'load more messages'
} else if (this.gotMorePosts) { } else if (this.gotMorePosts) {
var lastPost = oldPosts[oldOrder[prevState.numToDisplay]]; var lastPost = oldPosts[oldOrder[prevState.numToDisplay]];
$('#' + lastPost.id)[0].scrollIntoView(); $('#' + lastPost.id)[0].scrollIntoView();
this.gotMorePosts = false;
} else { } else {
this.scrollTo(this.prevScrollTop); this.scrollTo(this.prevScrollTop);
} }
} }
componentWillUpdate() { componentWillUpdate() {
var postHolder = $('.post-list-holder-by-time'); var postHolder = $(React.findDOMNode(this.refs.postlist));
this.prevScrollTop = postHolder.scrollTop(); this.prevScrollTop = postHolder.scrollTop();
} }
componentWillUnmount() { componentWillReceiveProps(nextProps) {
PostStore.removeChangeListener(this.onChange); if (nextProps.isActive === true && this.props.isActive === false) {
ChannelStore.removeChangeListener(this.onChange); this.activate();
UserStore.removeStatusesChangeListener(this.onTimeChange); } else if (nextProps.isActive === false && this.props.isActive === true) {
SocketStore.removeChangeListener(this.onSocketChange); this.deactivate();
$('body').off('click.userpopover'); }
$('.modal').off('show.bs.modal'); }
resize() {
const postHolder = $(React.findDOMNode(this.refs.postlist));
if ($('#create_post').length > 0) {
const height = $(window).height() - $('#create_post').height() - $('#error_bar').outerHeight() - 50;
postHolder.css('height', height + 'px');
}
} }
scrollTo(val) { scrollTo(val) {
this.isUserScroll = false; this.isUserScroll = false;
var postHolder = $('.post-list-holder-by-time'); var postHolder = $(React.findDOMNode(this.refs.postlist));
postHolder[0].scrollTop = val; postHolder[0].scrollTop = val;
} }
scrollToBottom(force) { scrollToBottom(force) {
this.isUserScroll = false; this.isUserScroll = false;
var postHolder = $('.post-list-holder-by-time'); var postHolder = $(React.findDOMNode(this.refs.postlist));
if ($('#new_message')[0] && !this.userHasSeenNew && !force) { if ($('#new_message')[0] && !this.userHasSeenNew && !force) {
$('#new_message')[0].scrollIntoView(); $('#new_message')[0].scrollIntoView();
} else { } else {
@@ -241,34 +228,32 @@ export default class PostList extends React.Component {
} }
} }
loadFirstPosts(id) { loadFirstPosts(id) {
if (this.loadInProgress) {
return;
}
if (this.props.channelId == null) {
return;
}
this.loadInProgress = true;
Client.getPosts( Client.getPosts(
id, id,
PostStore.getLatestUpdate(id), PostStore.getLatestUpdate(id),
function success() { function success() {
this.loadInProgress = false;
this.setState({isFirstLoadComplete: true}); this.setState({isFirstLoadComplete: true});
}.bind(this), }.bind(this),
function fail() { function fail() {
this.loadInProgress = false;
this.setState({isFirstLoadComplete: true}); this.setState({isFirstLoadComplete: true});
}.bind(this) }.bind(this)
); );
} }
onChange() { onChange() {
var newState = this.getStateFromStores(); var newState = this.getStateFromStores(this.props.channelId);
// Special case where the channel wasn't yet set in componentDidMount
if (!this.state.isFirstLoadComplete && this.state.channel.id == null && newState.channel.id != null) {
this.loadFirstPosts(newState.channel.id);
}
if (!utils.areStatesEqual(newState, this.state)) {
if (this.state.channel.id !== newState.channel.id) {
PostStore.clearUnseenDeletedPosts(this.state.channel.id);
this.userHasSeenNew = false;
newState.numToDisplay = Constants.POST_CHUNK_SIZE;
} else {
newState.lastViewed = this.state.lastViewed;
}
if (!utils.areStatesEqual(newState.postList, this.state.postList)) {
this.setState(newState); this.setState(newState);
} }
} }
@@ -424,7 +409,7 @@ export default class PostList extends React.Component {
} }
} }
var members = ChannelStore.getCurrentExtraInfo().members; var members = ChannelStore.getExtraInfo(channel.id).members;
for (var i = 0; i < members.length; i++) { for (var i = 0; i < members.length; i++) {
if (members[i].roles.indexOf('admin') > -1) { if (members[i].roles.indexOf('admin') > -1) {
return members[i].username; return members[i].username;
@@ -488,6 +473,11 @@ export default class PostList extends React.Component {
var userId = UserStore.getCurrentId(); var userId = UserStore.getCurrentId();
var renderedLastViewed = false; var renderedLastViewed = false;
var lastViewed = Number.MAX_VALUE;
if (ChannelStore.getMember(this.props.channelId) != null) {
lastViewed = ChannelStore.getMember(this.props.channelId).last_viewed_at;
}
var numToDisplay = this.state.numToDisplay; var numToDisplay = this.state.numToDisplay;
if (order.length - 1 < numToDisplay) { if (order.length - 1 < numToDisplay) {
@@ -543,7 +533,7 @@ export default class PostList extends React.Component {
); );
} }
if (post.user_id !== userId && post.create_at > this.state.lastViewed && !renderedLastViewed) { if (post.user_id !== userId && post.create_at > lastViewed && !renderedLastViewed) {
renderedLastViewed = true; renderedLastViewed = true;
// Temporary fix to solve ie10/11 rendering issue // Temporary fix to solve ie10/11 rendering issue
@@ -577,7 +567,7 @@ export default class PostList extends React.Component {
var posts = this.state.postList.posts; var posts = this.state.postList.posts;
var order = this.state.postList.order; var order = this.state.postList.order;
var channelId = this.state.channel.id; var channelId = this.props.channelId;
$(React.findDOMNode(this.refs.loadmore)).text('Retrieving more messages...'); $(React.findDOMNode(this.refs.loadmore)).text('Retrieving more messages...');
@@ -619,7 +609,7 @@ export default class PostList extends React.Component {
render() { render() {
var order = []; var order = [];
var posts; var posts;
var channel = this.state.channel; var channel = ChannelStore.get(this.props.channelId);
if (this.state.postList != null) { if (this.state.postList != null) {
posts = this.state.postList.posts; posts = this.state.postList.posts;
@@ -628,7 +618,7 @@ export default class PostList extends React.Component {
var moreMessages = <p className='beginning-messages-text'>Beginning of Channel</p>; var moreMessages = <p className='beginning-messages-text'>Beginning of Channel</p>;
if (channel != null) { if (channel != null) {
if (order.length > this.state.numToDisplay) { if (order.length >= this.state.numToDisplay) {
moreMessages = ( moreMessages = (
<a <a
ref='loadmore' ref='loadmore'
@@ -655,10 +645,15 @@ export default class PostList extends React.Component {
/>); />);
} }
var activeClass = '';
if (!this.props.isActive) {
activeClass = 'inactive';
}
return ( return (
<div <div
ref='postlist' ref='postlist'
className='post-list-holder-by-time' className={'post-list-holder-by-time ' + activeClass}
> >
<div className='post-list__table'> <div className='post-list__table'>
<div className='post-list__content'> <div className='post-list__content'>
@@ -670,3 +665,12 @@ export default class PostList extends React.Component {
); );
} }
} }
PostList.defaultProps = {
isActive: false,
channelId: null
};
PostList.propTypes = {
isActive: React.PropTypes.bool,
channelId: React.PropTypes.string
};

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

@@ -0,0 +1,62 @@
// Copyright (c) 2015 Spinpunch, Inc. All Rights Reserved.
// See License.txt for license information.
const PostList = require('./post_list.jsx');
const ChannelStore = require('../stores/channel_store.jsx');
export default class PostListContainer extends React.Component {
constructor() {
super();
this.onChange = this.onChange.bind(this);
this.onLeave = this.onLeave.bind(this);
let currentChannelId = ChannelStore.getCurrentId();
if (currentChannelId) {
this.state = {currentChannelId: currentChannelId, postLists: [currentChannelId]};
} else {
this.state = {currentChannelId: null, postLists: []};
}
}
componentDidMount() {
ChannelStore.addChangeListener(this.onChange);
ChannelStore.addLeaveListener(this.onLeave);
}
onChange() {
let channelId = ChannelStore.getCurrentId();
if (channelId === this.state.currentChannelId) {
return;
}
let postLists = this.state.postLists;
if (postLists.indexOf(channelId) === -1) {
postLists.push(channelId);
}
this.setState({currentChannelId: channelId, postLists: postLists});
}
onLeave(id) {
let postLists = this.state.postLists;
var index = postLists.indexOf(id);
if (index !== -1) {
postLists.splice(index, 1);
}
}
render() {
let postLists = this.state.postLists;
let channelId = this.state.currentChannelId;
let postListCtls = [];
for (let i = 0; i <= this.state.postLists.length - 1; i++) {
postListCtls.push(
<PostList
channelId={postLists[i]}
isActive={postLists[i] === channelId}
/>
);
}
return (
<div>{postListCtls}</div>
);
}
}

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

@@ -5,7 +5,7 @@ var AppDispatcher = require('../dispatcher/app_dispatcher.jsx');
var Navbar = require('../components/navbar.jsx'); var Navbar = require('../components/navbar.jsx');
var Sidebar = require('../components/sidebar.jsx'); var Sidebar = require('../components/sidebar.jsx');
var ChannelHeader = require('../components/channel_header.jsx'); var ChannelHeader = require('../components/channel_header.jsx');
var PostList = require('../components/post_list.jsx'); var PostListContainer = require('../components/post_list_container.jsx');
var CreatePost = require('../components/create_post.jsx'); var CreatePost = require('../components/create_post.jsx');
var SidebarRight = require('../components/sidebar_right.jsx'); var SidebarRight = require('../components/sidebar_right.jsx');
var SidebarRightMenu = require('../components/sidebar_right_menu.jsx'); var SidebarRightMenu = require('../components/sidebar_right_menu.jsx');
@@ -159,7 +159,7 @@ function setupChannelPage(teamName, teamType, teamId, channelName, channelId) {
); );
React.render( React.render(
<PostList />, <PostListContainer />,
document.getElementById('post-list') document.getElementById('post-list')
); );

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

@@ -10,6 +10,7 @@ var ActionTypes = Constants.ActionTypes;
var BrowserStore = require('../stores/browser_store.jsx'); var BrowserStore = require('../stores/browser_store.jsx');
var CHANGE_EVENT = 'change'; var CHANGE_EVENT = 'change';
var LEAVE_EVENT = 'leave';
var MORE_CHANGE_EVENT = 'change'; var MORE_CHANGE_EVENT = 'change';
var EXTRA_INFO_EVENT = 'extra_info'; var EXTRA_INFO_EVENT = 'extra_info';
@@ -48,6 +49,15 @@ class ChannelStoreClass extends EventEmitter {
removeExtraInfoChangeListener(callback) { removeExtraInfoChangeListener(callback) {
this.removeListener(EXTRA_INFO_EVENT, callback); this.removeListener(EXTRA_INFO_EVENT, callback);
} }
emitLeave(id) {
this.emit(LEAVE_EVENT, id);
}
addLeaveListener(callback) {
this.on(LEAVE_EVENT, callback);
}
removeLeaveListener(callback) {
this.removeListener(LEAVE_EVENT, callback);
}
findFirstBy(field, value) { findFirstBy(field, value) {
var channels = this.pGetChannels(); var channels = this.pGetChannels();
for (var i = 0; i < channels.length; i++) { for (var i = 0; i < channels.length; i++) {
@@ -272,6 +282,10 @@ ChannelStore.dispatchToken = AppDispatcher.register(function handleAction(payloa
ChannelStore.emitExtraInfoChange(); ChannelStore.emitExtraInfoChange();
break; break;
case ActionTypes.LEAVE_CHANNEL:
ChannelStore.emitLeave(action.id);
break;
default: default:
break; break;
} }

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

@@ -9,6 +9,7 @@ module.exports = {
CLICK_CHANNEL: null, CLICK_CHANNEL: null,
CREATE_CHANNEL: null, CREATE_CHANNEL: null,
LEAVE_CHANNEL: null,
RECIEVED_CHANNELS: null, RECIEVED_CHANNELS: null,
RECIEVED_CHANNEL: null, RECIEVED_CHANNEL: null,
RECIEVED_MORE_CHANNELS: null, RECIEVED_MORE_CHANNELS: null,

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

@@ -143,6 +143,12 @@ body.ios {
&.hide-scroll::-webkit-scrollbar { &.hide-scroll::-webkit-scrollbar {
width: 0px !important; width: 0px !important;
} }
&.inactive {
display: none;
}
&.active {
display: inline;
}
} }
.post-list__table { .post-list__table {
display: table; display: table;