diff --git a/js/src/forum/components/DiscussionPage.js b/js/src/forum/components/DiscussionPage.js index 8d51ca7c8..bff23ac01 100644 --- a/js/src/forum/components/DiscussionPage.js +++ b/js/src/forum/components/DiscussionPage.js @@ -109,7 +109,7 @@ export default class DiscussionPage extends Page {
- {PostStream.component({ discussion, state: this.stream, positionHandler: this.positionChanged.bind(this) })} + {PostStream.component({ discussion, stream: this.stream, onPositionChange: this.positionChanged.bind(this) })}
, ] @@ -268,7 +268,7 @@ export default class DiscussionPage extends Page { 'scrubber', PostStreamScrubber.component({ discussion: this.discussion, - state: this.stream, + stream: this.stream, className: 'App-titleControl', }), -100 diff --git a/js/src/forum/components/PostStream.js b/js/src/forum/components/PostStream.js index 3dad39a34..dc204420f 100644 --- a/js/src/forum/components/PostStream.js +++ b/js/src/forum/components/PostStream.js @@ -11,12 +11,13 @@ import Button from '../../common/components/Button'; * ### Props * * - `discussion` - * - `state` + * - `stream` + * - `onPositionChange` */ export default class PostStream extends Component { init() { this.discussion = this.props.discussion; - this.state = this.props.state; + this.stream = this.props.stream; this.scrollListener = new ScrollListener(this.onscroll.bind(this)); } @@ -29,13 +30,13 @@ export default class PostStream extends Component { let lastTime; - const viewingEnd = this.state.viewingEnd(); - const posts = this.state.posts(); + const viewingEnd = this.stream.viewingEnd(); + const posts = this.stream.posts(); const postIds = this.discussion.postIds(); const items = posts.map((post, i) => { let content; - const attrs = { 'data-index': this.state.visibleStart + i }; + const attrs = { 'data-index': this.stream.visibleStart + i }; if (post) { const time = post.createdAt(); @@ -65,7 +66,7 @@ export default class PostStream extends Component { lastTime = time; } else { - attrs.key = 'post' + postIds[this.state.visibleStart + i]; + attrs.key = 'post' + postIds[this.stream.visibleStart + i]; content = PostLoading.component(); } @@ -77,10 +78,10 @@ export default class PostStream extends Component { ); }); - if (!viewingEnd && posts[this.state.visibleEnd - this.state.visibleStart - 1]) { + if (!viewingEnd && posts[this.stream.visibleEnd - this.stream.visibleStart - 1]) { items.push(
-
@@ -101,17 +102,17 @@ export default class PostStream extends Component { } config(isInitialized, context) { - if (this.state.needsScroll) { - this.state.needsScroll = false; - const locationType = this.state.locationType; + if (this.stream.needsScroll) { + this.stream.needsScroll = false; + const locationType = this.stream.locationType; if (locationType == 'number') { - this.scrollToNumber(this.state.number, this.state.noAnimationScroll); + this.scrollToNumber(this.stream.number, this.stream.noAnimationScroll); } else if (locationType == 'index') { - const index = this.state.sanitizeIndex(this.state.index); - const backwards = index == this.state.count() - 1; - this.scrollToIndex(index, this.state.noAnimationScroll, backwards); + const index = this.stream.sanitizeIndex(this.stream.index); + const backwards = index == this.stream.count() - 1; + this.scrollToIndex(index, this.stream.noAnimationScroll, backwards); } - this[locationType] = this.state[locationType]; + this[locationType] = this.stream[locationType]; } if (isInitialized) return; @@ -132,25 +133,25 @@ export default class PostStream extends Component { * @param {Integer} top */ onscroll(top = window.pageYOffset) { - if (this.state.paused) return; + if (this.stream.paused) return; const marginTop = this.getMarginTop(); const viewportHeight = $(window).height() - marginTop; const viewportTop = top + marginTop; const loadAheadDistance = 300; - if (this.state.visibleStart > 0) { - const $item = this.$('.PostStream-item[data-index=' + this.state.visibleStart + ']'); + if (this.stream.visibleStart > 0) { + const $item = this.$('.PostStream-item[data-index=' + this.stream.visibleStart + ']'); if ($item.length && $item.offset().top > viewportTop - loadAheadDistance) { - this.state.loadPrevious(); + this.stream.loadPrevious(); } } - if (this.state.visibleEnd < this.state.count()) { - const $item = this.$('.PostStream-item[data-index=' + (this.state.visibleEnd - 1) + ']'); + if (this.stream.visibleEnd < this.stream.count()) { + const $item = this.$('.PostStream-item[data-index=' + (this.stream.visibleEnd - 1) + ']'); if ($item.length && $item.offset().top + $item.outerHeight(true) < viewportTop + viewportHeight + loadAheadDistance) { - this.state.loadNext(); + this.stream.loadNext(); } } @@ -214,9 +215,9 @@ export default class PostStream extends Component { if (time) period = time; }); - this.state.index = index + 1; - this.state.visible = visible; - if (period) this.state.description = dayjs(period).format('MMMM YYYY'); + this.stream.index = index + 1; + this.stream.visible = visible; + if (period) this.stream.description = dayjs(period).format('MMMM YYYY'); } /** @@ -255,7 +256,7 @@ export default class PostStream extends Component { }); if (startNumber) { - this.props.positionHandler(startNumber || 1, endNumber, startNumber); + this.props.onPositionChange(startNumber || 1, endNumber, startNumber); } } @@ -285,7 +286,7 @@ export default class PostStream extends Component { const $item = this.$(`.PostStream-item[data-index=${index}]`); return this.scrollToItem($item, noAnimation, true, bottom).then(() => { - if (index == this.state.count() - 1) { + if (index == this.stream.count() - 1) { this.flashItem(this.$('.PostStream-item:last-child')); } }); @@ -325,14 +326,14 @@ export default class PostStream extends Component { } } - return Promise.all([$container.promise(), this.state.loadPromise]).then(() => { + return Promise.all([$container.promise(), this.stream.loadPromise]).then(() => { this.updateScrubber(); const index = $item.data('index'); m.redraw(true); const scroll = index == 0 ? 0 : $(`.PostStream-item[data-index=${$item.data('index')}]`).offset().top - this.getMarginTop(); $(window).scrollTop(scroll); this.calculatePosition(); - this.state.paused = false; + this.stream.paused = false; }); } diff --git a/js/src/forum/components/PostStreamScrubber.js b/js/src/forum/components/PostStreamScrubber.js index 3b18cb2a7..5371c8c04 100644 --- a/js/src/forum/components/PostStreamScrubber.js +++ b/js/src/forum/components/PostStreamScrubber.js @@ -9,19 +9,19 @@ import ScrollListener from '../../common/utils/ScrollListener'; * * ### Props * - * - `state` + * - `stream` * - `className` */ export default class PostStreamScrubber extends Component { init() { - this.state = this.props.state; + this.stream = this.props.stream; this.handlers = {}; this.scrollListener = new ScrollListener(this.updateScrubberValues.bind(this, { fromScroll: true, forceHeightChange: true })); } view() { - const count = this.state.count(); + const count = this.stream.count(); // Index is left blank for performance reasons, it is filled in in updateScubberValues const viewing = app.translator.transChoice('core.forum.post_scrubber.viewing_text', count, { @@ -29,8 +29,8 @@ export default class PostStreamScrubber extends Component { count: {formatNumber(count)}, }); - const unreadCount = this.state.discussion.unreadCount(); - const unreadPercent = count ? Math.min(count - this.state.index, unreadCount) / count : 0; + const unreadCount = this.stream.discussion.unreadCount(); + const unreadPercent = count ? Math.min(count - this.stream.index, unreadCount) / count : 0; function styleUnread(element, isInitialized, context) { const $element = $(element); @@ -68,7 +68,7 @@ export default class PostStreamScrubber extends Component {
{viewing} - {this.state.description} + {this.stream.description}
@@ -88,7 +88,7 @@ export default class PostStreamScrubber extends Component { } config(isInitialized, context) { - this.state.loadPromise.then(() => this.updateScrubberValues({ animate: true, forceHeightChange: true })); + this.stream.loadPromise.then(() => this.updateScrubberValues({ animate: true, forceHeightChange: true })); if (isInitialized) return; context.onunload = this.ondestroy.bind(this); @@ -142,24 +142,24 @@ export default class PostStreamScrubber extends Component { * @param {Boolean} animate */ updateScrubberValues(options = {}) { - const index = this.state.index; - const count = this.state.count(); - const visible = this.state.visible || 1; + const index = this.stream.index; + const count = this.stream.count(); + const visible = this.stream.visible || 1; const percentPerPost = this.percentPerPost(); const $scrubber = this.$(); - $scrubber.find('.Scrubber-index').text(formatNumber(this.state.sanitizeIndex(Math.max(1, index)))); - $scrubber.find('.Scrubber-description').text(this.state.description); - $scrubber.toggleClass('disabled', this.state.disabled()); + $scrubber.find('.Scrubber-index').text(formatNumber(this.stream.sanitizeIndex(Math.max(1, index)))); + $scrubber.find('.Scrubber-description').text(this.stream.description); + $scrubber.toggleClass('disabled', this.stream.disabled()); const heights = {}; heights.before = Math.max(0, percentPerPost.index * Math.min(index - 1, count - visible)); heights.handle = Math.min(100 - heights.before, percentPerPost.visible * visible); heights.after = 100 - heights.before - heights.handle; - // If the state is paused, don't change height on scroll, as the viewport is being scrolled by the JS + // If the stream is paused, don't change height on scroll, as the viewport is being scrolled by the JS // If a height change animation is already in progress, don't adjust height unless overriden - if ((options.fromScroll && this.state.paused) || (this.adjustingHeight && !options.forceHeightChange)) return; + if ((options.fromScroll && this.stream.paused) || (this.adjustingHeight && !options.forceHeightChange)) return; const func = options.animate ? 'animate' : 'css'; this.adjustingHeight = true; @@ -184,7 +184,7 @@ export default class PostStreamScrubber extends Component { * Go to the first post in the discussion. */ goToFirst() { - this.state.goToFirst(); + this.stream.goToFirst(); this.updateScrubberValues({ animate: true, forceHeightChange: true }); } @@ -192,7 +192,7 @@ export default class PostStreamScrubber extends Component { * Go to the last post in the discussion. */ goToLast() { - this.state.goToLast(); + this.stream.goToLast(); this.updateScrubberValues({ animate: true, forceHeightChange: true }); } @@ -222,7 +222,7 @@ export default class PostStreamScrubber extends Component { onmousedown(e) { e.redraw = false; this.mouseStart = e.clientY || e.originalEvent.touches[0].clientY; - this.indexStart = this.state.index; + this.indexStart = this.stream.index; this.dragging = true; $('body').css('cursor', 'move'); this.$().toggleClass('dragging', this.dragging); @@ -238,9 +238,9 @@ export default class PostStreamScrubber extends Component { const deltaPixels = (e.clientY || e.originalEvent.touches[0].clientY) - this.mouseStart; const deltaPercent = (deltaPixels / this.$('.Scrubber-scrollbar').outerHeight()) * 100; const deltaIndex = deltaPercent / this.percentPerPost().index || 0; - const newIndex = Math.min(this.indexStart + deltaIndex, this.state.count() - 1); + const newIndex = Math.min(this.indexStart + deltaIndex, this.stream.count() - 1); - this.state.index = Math.max(0, newIndex); + this.stream.index = Math.max(0, newIndex); this.updateScrubberValues(); } @@ -257,8 +257,8 @@ export default class PostStreamScrubber extends Component { // If the index we've landed on is in a gap, then tell the stream- // content that we want to load those posts. - const intIndex = Math.floor(this.state.index); - this.state.goToIndex(intIndex); + const intIndex = Math.floor(this.stream.index); + this.stream.goToIndex(intIndex); } onclick(e) { @@ -278,8 +278,8 @@ export default class PostStreamScrubber extends Component { // 3. Now we can convert the percentage into an index, and tell the stream- // content component to jump to that index. let offsetIndex = offsetPercent / this.percentPerPost().index; - offsetIndex = Math.max(0, Math.min(this.state.count() - 1, offsetIndex)); - this.state.goToIndex(Math.floor(offsetIndex)); + offsetIndex = Math.max(0, Math.min(this.stream.count() - 1, offsetIndex)); + this.stream.goToIndex(Math.floor(offsetIndex)); this.updateScrubberValues({ animate: true, forceHeightChange: true }); this.$().removeClass('open'); @@ -296,8 +296,8 @@ export default class PostStreamScrubber extends Component { * scrubber. */ percentPerPost() { - const count = this.state.count() || 1; - const visible = this.state.visible || 1; + const count = this.stream.count() || 1; + const visible = this.stream.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