diff --git a/js/src/forum/components/PostStream.js b/js/src/forum/components/PostStream.js index e502624d2..31cbce362 100644 --- a/js/src/forum/components/PostStream.js +++ b/js/src/forum/components/PostStream.js @@ -3,7 +3,6 @@ import ScrollListener from '../../common/utils/ScrollListener'; import PostLoading from './LoadingPost'; import ReplyPlaceholder from './ReplyPlaceholder'; import Button from '../../common/components/Button'; -import anchorScroll from '../../common/utils/anchorScroll'; /** * The `PostStream` component displays an infinitely-scrollable wall of posts in @@ -219,13 +218,9 @@ export default class PostStream extends Component { } }); - const indexChanged = Math.floor(this.state.index) != Math.floor(index); this.state.index = index; - this.state.visible = visible; + this.state.visible(visible); this.state.description = period ? dayjs(period).format('MMMM YYYY') : ''; - if (indexChanged) { - m.redraw(); - } } /** diff --git a/js/src/forum/components/PostStreamScrubber.js b/js/src/forum/components/PostStreamScrubber.js index 04317325a..b4dd8b31b 100644 --- a/js/src/forum/components/PostStreamScrubber.js +++ b/js/src/forum/components/PostStreamScrubber.js @@ -1,6 +1,7 @@ import Component from '../../common/Component'; import icon from '../../common/helpers/icon'; import formatNumber from '../../common/utils/formatNumber'; +import ScrollListener from '../../common/utils/ScrollListener'; /** * The `PostStreamScrubber` component displays a scrubber which can be used to @@ -15,12 +16,14 @@ export default class PostStreamScrubber extends Component { init() { this.state = this.props.state; this.handlers = {}; + + this.scrollListener = new ScrollListener(this.updateScrubberValues.bind(this)); } view() { const index = this.state.index; const count = this.state.count(); - const visible = this.state.visible || 1; + const visible = this.state.visible() || 1; const unreadCount = this.state.discussion.unreadCount(); const unreadPercent = count ? Math.min(count - this.state.index, unreadCount) / count : 0; @@ -104,7 +107,7 @@ export default class PostStreamScrubber extends Component { */ percentPerPost() { const count = this.state.count() || 1; - const visible = this.state.visible || 1; + const visible = this.state.visible() || 1; // To stop the handle of the scrollbar from getting too small when there // are many posts, we define a minimum percentage height for the handle @@ -179,9 +182,12 @@ export default class PostStreamScrubber extends Component { $(document) .on('mousemove touchmove', (this.handlers.onmousemove = this.onmousemove.bind(this))) .on('mouseup touchend', (this.handlers.onmouseup = this.onmouseup.bind(this))); + + setTimeout(() => this.scrollListener.start()); } ondestroy() { + this.scrollListener.stop(); $(window).off('resize', this.handlers.onresize); $(document).off('mousemove touchmove', this.handlers.onmousemove).off('mouseup touchend', this.handlers.onmouseup); @@ -208,6 +214,7 @@ export default class PostStreamScrubber extends Component { this.indexStart = this.state.index; this.dragging = true; $('body').css('cursor', 'move'); + this.$().toggleClass('dragging', this.dragging); } onmousemove(e) { @@ -223,10 +230,11 @@ export default class PostStreamScrubber extends Component { const newIndex = Math.min(this.indexStart + deltaIndex, this.state.count() - 1); this.state.index = Math.max(0, newIndex); - m.redraw(); + this.updateScrubberValues(); } onmouseup() { + this.$().toggleClass('dragging', this.dragging); if (!this.dragging) return; this.mouseStart = 0; @@ -264,4 +272,25 @@ export default class PostStreamScrubber extends Component { this.$().removeClass('open'); } + + updateScrubberValues() { + console.log(this.dragging); + const index = this.state.index; + const count = this.state.count(); + const visible = this.state.visible() || 1; + const percentPerPost = this.percentPerPost(); + + this.$(`.Scrubber-index`).html(formatNumber(this.state.sanitizeIndex(index + 1))); + + const heights = {}; + heights.before = Math.max(0, percentPerPost.index * Math.min(index, count - visible)); + heights.handle = Math.min(100 - heights.before, percentPerPost.visible * visible); + heights.after = 100 - heights.before - heights.handle; + + for (const part in heights) { + this.$(`.Scrubber-${part}`).css('height', heights[part] + '%'); + } + + this.$().toggleClass('disabled', this.state.allVisible()); + } } diff --git a/js/src/forum/states/PostStreamState.js b/js/src/forum/states/PostStreamState.js index a60d588b7..14d1bab8e 100644 --- a/js/src/forum/states/PostStreamState.js +++ b/js/src/forum/states/PostStreamState.js @@ -29,7 +29,7 @@ class PostStreamState { * * @type {Number} */ - this.visible = 1; + this.visible = m.prop(1); /** * The description to render on the scrubber. @@ -173,7 +173,7 @@ class PostStreamState { * @return {Boolean} */ allVisible() { - return this.visible >= this.count(); + return this.visible() >= this.count(); } /** diff --git a/less/forum/Scrubber.less b/less/forum/Scrubber.less index 8044ecb04..d23e1857a 100644 --- a/less/forum/Scrubber.less +++ b/less/forum/Scrubber.less @@ -21,13 +21,13 @@ } .Scrubber-before, .Scrubber-after { border-left: 1px solid @control-bg; - transition: height 0.15s ease-out; + transition: height 0.15s linear; } -.Scrubber-before, .Scrubber-after { +.Scrubber-handle { border-left: 1px solid @control-bg; - transition: height 0.15s ease-out; + transition: height 0.25s ease-in; } -.dragging .Scrubber-before, .dragging .Scrubber-after { +.dragging .Scrubber-before, .dragging .Scrubber-after, .dragging .Scrubber-handle { transition: none; } .Scrubber-unread {