summaryrefslogtreecommitdiffstats
path: root/web
diff options
context:
space:
mode:
authorJoramWilander <jwawilander@gmail.com>2015-09-08 10:11:57 -0400
committerJoramWilander <jwawilander@gmail.com>2015-09-08 10:11:57 -0400
commit5c0680397de9d3cfd0018743e0b1d58dfbdca25d (patch)
treed28188a33e20e3d8c90cb4ad17a1f300970df97f /web
parent5b3ee66dc3baff35104bc6e6c8f25c4474005974 (diff)
downloadchat-5c0680397de9d3cfd0018743e0b1d58dfbdca25d.tar.gz
chat-5c0680397de9d3cfd0018743e0b1d58dfbdca25d.tar.bz2
chat-5c0680397de9d3cfd0018743e0b1d58dfbdca25d.zip
Add post list container to hold mounted post lists for faster rendering/channel switching.
Diffstat (limited to 'web')
-rw-r--r--web/react/components/channel_header.jsx7
-rw-r--r--web/react/components/channel_loader.jsx60
-rw-r--r--web/react/components/post_list.jsx202
-rw-r--r--web/react/components/post_list_container.jsx62
-rw-r--r--web/react/pages/channel.jsx4
-rw-r--r--web/react/stores/channel_store.jsx14
-rw-r--r--web/react/utils/constants.jsx1
-rw-r--r--web/sass-files/sass/partials/_post.scss6
8 files changed, 250 insertions, 106 deletions
diff --git a/web/react/components/channel_header.jsx b/web/react/components/channel_header.jsx
index 87b9cab04..db23a5831 100644
--- a/web/react/components/channel_header.jsx
+++ b/web/react/components/channel_header.jsx
@@ -64,9 +64,14 @@ export default class ChannelHeader extends React.Component {
handleLeave() {
Client.leaveChannel(this.state.channel.id,
function handleLeaveSuccess() {
+ AppDispatcher.handleViewAction({
+ type: ActionTypes.LEAVE_CHANNEL,
+ id: this.state.channel.id
+ });
+
const townsquare = ChannelStore.getByName('town-square');
Utils.switchChannel(townsquare);
- },
+ }.bind(this),
function handleLeaveError(err) {
AsyncClient.dispatchError(err, 'handleLeave');
}
diff --git a/web/react/components/channel_loader.jsx b/web/react/components/channel_loader.jsx
index 8e8ed3f73..ce6f60f87 100644
--- a/web/react/components/channel_loader.jsx
+++ b/web/react/components/channel_loader.jsx
@@ -17,6 +17,8 @@ export default class ChannelLoader extends React.Component {
constructor(props) {
super(props);
+ this.intervalId = null;
+
this.onSocketChange = this.onSocketChange.bind(this);
this.state = {};
@@ -35,10 +37,12 @@ export default class ChannelLoader extends React.Component {
PostStore.clearPendingPosts();
/* Set up interval functions */
- setInterval(
+ this.intervalId = setInterval(
function pollStatuses() {
AsyncClient.getStatuses();
- }, 30000);
+ },
+ 30000
+ );
/* Device tracking setup */
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 */
window.isActive = true;
- $(window).focus(function windowFocus() {
+ $(window).on('focus', function windowFocus() {
AsyncClient.updateLastViewedAt();
window.isActive = true;
});
- $(window).blur(function windowBlur() {
+ $(window).on('blur', function windowBlur() {
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) + ';');
$('.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) {
if (msg && msg.user_id && msg.user_id !== UserStore.getCurrentId()) {
diff --git a/web/react/components/post_list.jsx b/web/react/components/post_list.jsx
index 6fa87ca4a..d7c0d4862 100644
--- a/web/react/components/post_list.jsx
+++ b/web/react/components/post_list.jsx
@@ -18,8 +18,8 @@ var ActionTypes = Constants.ActionTypes;
import {strings} from '../utils/config.js';
export default class PostList extends React.Component {
- constructor() {
- super();
+ constructor(props) {
+ super(props);
this.gotMorePosts = false;
this.scrolled = false;
@@ -27,6 +27,7 @@ export default class PostList extends React.Component {
this.seenNewMessages = false;
this.isUserScroll = true;
this.userHasSeenNew = false;
+ this.loadInProgress = false;
this.onChange = this.onChange.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.loadMorePosts = this.loadMorePosts.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.isFirstLoadComplete = false;
}
- getStateFromStores() {
- var channel = ChannelStore.getCurrent();
-
- if (channel == null) {
- channel = {};
- }
-
- var postList = PostStore.getCurrentPosts();
+ getStateFromStores(id) {
+ var postList = PostStore.getPosts(id);
if (postList != null) {
- var deletedPosts = PostStore.getUnseenDeletedPosts(channel.id);
+ var deletedPosts = PostStore.getUnseenDeletedPosts(id);
if (deletedPosts && Object.keys(deletedPosts).length > 0) {
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) {
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 {
- postList: postList,
- channel: channel,
- lastViewed: lastViewed
+ postList: postList
};
}
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);
- ChannelStore.addChangeListener(this.onChange);
UserStore.addStatusesChangeListener(this.onTimeChange);
SocketStore.addChangeListener(this.onSocketChange);
- var postHolder = $('.post-list-holder-by-time');
-
- $('.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');
- }
+ var postHolder = $(React.findDOMNode(this.refs.postlist));
+ $(window).on('resize.' + this.props.channelId, function resize() {
+ this.resize();
if (!this.scrolled) {
this.scrollToBottom();
}
}.bind(this));
- postHolder.scroll(function scroll() {
+ postHolder.on('scroll', function scroll() {
var position = postHolder.scrollTop() + postHolder.height() + 14;
var bottom = postHolder[0].scrollHeight;
@@ -134,41 +131,25 @@ export default class PostList extends React.Component {
this.isUserScroll = true;
}.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:last-child .post').addClass('post--last');
- $('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');
- }
- });
+ if (!this.state.isFirstLoadComplete) {
+ this.loadFirstPosts(this.props.channelId);
+ }
+ this.resize();
+ this.onChange();
this.scrollToBottom();
-
- if (this.state.channel.id != null) {
- this.loadFirstPosts(this.state.channel.id);
- }
+ }
+ 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) {
$('.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 isNewPost = oldOrder.indexOf(order[0]) === -1;
- if (this.state.channel.id !== prevState.channel.id) {
+ if (this.props.isActive && !prevProps.isActive) {
this.scrollToBottom();
} else if (oldOrder.length === 0) {
this.scrollToBottom();
@@ -201,37 +182,43 @@ export default class PostList extends React.Component {
} else if (isNewPost &&
userId === firstPost.user_id &&
!utils.isComment(firstPost)) {
- this.state.lastViewed = utils.getTimestamp();
this.scrollToBottom(true);
// the user clicked 'load more messages'
} else if (this.gotMorePosts) {
var lastPost = oldPosts[oldOrder[prevState.numToDisplay]];
$('#' + lastPost.id)[0].scrollIntoView();
+ this.gotMorePosts = false;
} else {
this.scrollTo(this.prevScrollTop);
}
}
componentWillUpdate() {
- var postHolder = $('.post-list-holder-by-time');
+ var postHolder = $(React.findDOMNode(this.refs.postlist));
this.prevScrollTop = postHolder.scrollTop();
}
- componentWillUnmount() {
- PostStore.removeChangeListener(this.onChange);
- ChannelStore.removeChangeListener(this.onChange);
- UserStore.removeStatusesChangeListener(this.onTimeChange);
- SocketStore.removeChangeListener(this.onSocketChange);
- $('body').off('click.userpopover');
- $('.modal').off('show.bs.modal');
+ componentWillReceiveProps(nextProps) {
+ if (nextProps.isActive === true && this.props.isActive === false) {
+ this.activate();
+ } else if (nextProps.isActive === false && this.props.isActive === true) {
+ this.deactivate();
+ }
+ }
+ 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) {
this.isUserScroll = false;
- var postHolder = $('.post-list-holder-by-time');
+ var postHolder = $(React.findDOMNode(this.refs.postlist));
postHolder[0].scrollTop = val;
}
scrollToBottom(force) {
this.isUserScroll = false;
- var postHolder = $('.post-list-holder-by-time');
+ var postHolder = $(React.findDOMNode(this.refs.postlist));
if ($('#new_message')[0] && !this.userHasSeenNew && !force) {
$('#new_message')[0].scrollIntoView();
} else {
@@ -241,34 +228,32 @@ export default class PostList extends React.Component {
}
}
loadFirstPosts(id) {
+ if (this.loadInProgress) {
+ return;
+ }
+
+ if (this.props.channelId == null) {
+ return;
+ }
+
+ this.loadInProgress = true;
Client.getPosts(
id,
PostStore.getLatestUpdate(id),
function success() {
+ this.loadInProgress = false;
this.setState({isFirstLoadComplete: true});
}.bind(this),
function fail() {
+ this.loadInProgress = false;
this.setState({isFirstLoadComplete: true});
}.bind(this)
);
}
onChange() {
- var newState = this.getStateFromStores();
-
- // 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;
- }
+ var newState = this.getStateFromStores(this.props.channelId);
+ if (!utils.areStatesEqual(newState.postList, this.state.postList)) {
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++) {
if (members[i].roles.indexOf('admin') > -1) {
return members[i].username;
@@ -488,6 +473,11 @@ export default class PostList extends React.Component {
var userId = UserStore.getCurrentId();
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;
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;
// 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 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...');
@@ -619,7 +609,7 @@ export default class PostList extends React.Component {
render() {
var order = [];
var posts;
- var channel = this.state.channel;
+ var channel = ChannelStore.get(this.props.channelId);
if (this.state.postList != null) {
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>;
if (channel != null) {
- if (order.length > this.state.numToDisplay) {
+ if (order.length >= this.state.numToDisplay) {
moreMessages = (
<a
ref='loadmore'
@@ -655,10 +645,15 @@ export default class PostList extends React.Component {
/>);
}
+ var activeClass = '';
+ if (!this.props.isActive) {
+ activeClass = 'inactive';
+ }
+
return (
<div
ref='postlist'
- className='post-list-holder-by-time'
+ className={'post-list-holder-by-time ' + activeClass}
>
<div className='post-list__table'>
<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
+};
diff --git a/web/react/components/post_list_container.jsx b/web/react/components/post_list_container.jsx
new file mode 100644
index 000000000..0815ac883
--- /dev/null
+++ b/web/react/components/post_list_container.jsx
@@ -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>
+ );
+ }
+}
diff --git a/web/react/pages/channel.jsx b/web/react/pages/channel.jsx
index 71a03cde0..182721bef 100644
--- a/web/react/pages/channel.jsx
+++ b/web/react/pages/channel.jsx
@@ -5,7 +5,7 @@ var AppDispatcher = require('../dispatcher/app_dispatcher.jsx');
var Navbar = require('../components/navbar.jsx');
var Sidebar = require('../components/sidebar.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 SidebarRight = require('../components/sidebar_right.jsx');
var SidebarRightMenu = require('../components/sidebar_right_menu.jsx');
@@ -159,7 +159,7 @@ function setupChannelPage(teamName, teamType, teamId, channelName, channelId) {
);
React.render(
- <PostList />,
+ <PostListContainer />,
document.getElementById('post-list')
);
diff --git a/web/react/stores/channel_store.jsx b/web/react/stores/channel_store.jsx
index bd655b767..b9ba37c27 100644
--- a/web/react/stores/channel_store.jsx
+++ b/web/react/stores/channel_store.jsx
@@ -10,6 +10,7 @@ var ActionTypes = Constants.ActionTypes;
var BrowserStore = require('../stores/browser_store.jsx');
var CHANGE_EVENT = 'change';
+var LEAVE_EVENT = 'leave';
var MORE_CHANGE_EVENT = 'change';
var EXTRA_INFO_EVENT = 'extra_info';
@@ -48,6 +49,15 @@ class ChannelStoreClass extends EventEmitter {
removeExtraInfoChangeListener(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) {
var channels = this.pGetChannels();
for (var i = 0; i < channels.length; i++) {
@@ -272,6 +282,10 @@ ChannelStore.dispatchToken = AppDispatcher.register(function handleAction(payloa
ChannelStore.emitExtraInfoChange();
break;
+ case ActionTypes.LEAVE_CHANNEL:
+ ChannelStore.emitLeave(action.id);
+ break;
+
default:
break;
}
diff --git a/web/react/utils/constants.jsx b/web/react/utils/constants.jsx
index 18b7ff59c..7ead079d7 100644
--- a/web/react/utils/constants.jsx
+++ b/web/react/utils/constants.jsx
@@ -9,6 +9,7 @@ module.exports = {
CLICK_CHANNEL: null,
CREATE_CHANNEL: null,
+ LEAVE_CHANNEL: null,
RECIEVED_CHANNELS: null,
RECIEVED_CHANNEL: null,
RECIEVED_MORE_CHANNELS: null,
diff --git a/web/sass-files/sass/partials/_post.scss b/web/sass-files/sass/partials/_post.scss
index 231e6fe3f..a8e77f7d5 100644
--- a/web/sass-files/sass/partials/_post.scss
+++ b/web/sass-files/sass/partials/_post.scss
@@ -143,6 +143,12 @@ body.ios {
&.hide-scroll::-webkit-scrollbar {
width: 0px !important;
}
+ &.inactive {
+ display: none;
+ }
+ &.active {
+ display: inline;
+ }
}
.post-list__table {
display: table;