diff --git a/js/src/forum/components/DiscussionPage.js b/js/src/forum/components/DiscussionPage.js
index 4492879e3..a3cfb0074 100644
--- a/js/src/forum/components/DiscussionPage.js
+++ b/js/src/forum/components/DiscussionPage.js
@@ -109,7 +109,12 @@ export default class DiscussionPage extends Page {
{listItems(this.sidebarItems().toArray())}
- {PostStream.component({ discussion, stream: this.stream, onPositionChange: this.positionChanged.bind(this) })}
+ {PostStream.component({
+ discussion,
+ stream: this.stream,
+ targetPost: this.stream.targetPost,
+ onPositionChange: this.positionChanged.bind(this),
+ })}
,
]
diff --git a/js/src/forum/components/PostStream.js b/js/src/forum/components/PostStream.js
index 7fca157ea..ec8c61fd4 100644
--- a/js/src/forum/components/PostStream.js
+++ b/js/src/forum/components/PostStream.js
@@ -12,6 +12,7 @@ import Button from '../../common/components/Button';
*
* - `discussion`
* - `stream`
+ * - `targetPost`
* - `onPositionChange`
*/
export default class PostStream extends Component {
@@ -102,14 +103,7 @@ export default class PostStream extends Component {
}
config(isInitialized, context) {
- this.stream.scrollEffect((type, position, animate) => {
- if (type === 'number') {
- this.scrollToNumber(position, animate);
- } else if (type === 'index') {
- const backwards = position === this.stream.count() - 1;
- this.scrollToIndex(position, animate, backwards);
- }
- });
+ this.triggerScroll();
if (isInitialized) return;
@@ -123,6 +117,30 @@ export default class PostStream extends Component {
};
}
+ /**
+ * Start scrolling, if appropriate, to a newly-targeted post.
+ */
+ triggerScroll() {
+ if (!this.props.targetPost) return;
+
+ const oldTarget = this.prevTarget;
+ const newTarget = this.props.targetPost;
+
+ if (oldTarget) {
+ if ('number' in oldTarget && oldTarget.number === newTarget.number) return;
+ if ('index' in oldTarget && oldTarget.index === newTarget.index) return;
+ }
+
+ if ('number' in newTarget) {
+ this.scrollToNumber(newTarget.number, this.stream.noAnimationScroll);
+ } else if ('index' in newTarget) {
+ const backwards = newTarget.index === this.stream.count() - 1;
+ this.scrollToIndex(newTarget.index, this.stream.noAnimationScroll, backwards);
+ }
+
+ this.prevTarget = newTarget;
+ }
+
/**
* When the window is scrolled, check if either extreme of the post stream is
* in the viewport, and if so, trigger loading the next/previous page.
diff --git a/js/src/forum/states/PostStreamState.js b/js/src/forum/states/PostStreamState.js
index a226394f4..b01bfd12f 100644
--- a/js/src/forum/states/PostStreamState.js
+++ b/js/src/forum/states/PostStreamState.js
@@ -20,7 +20,6 @@ class PostStreamState {
this.loadPageTimeouts = {};
this.pagesLoading = 0;
- this.locationType = null;
this.index = 0;
this.number = 1;
@@ -92,9 +91,8 @@ class PostStreamState {
this.loadPromise = this.loadNearNumber(number);
- this.needsScroll = true;
+ this.targetPost = { number };
this.noAnimationScroll = noAnimation;
- this.locationType = 'number';
this.number = number;
// In this case, the redraw is only called after the response has been loaded
@@ -117,9 +115,8 @@ class PostStreamState {
this.loadPromise = this.loadNearIndex(index);
- this.needsScroll = true;
+ this.targetPost = { index };
this.noAnimationScroll = noAnimation;
- this.locationType = 'index';
this.index = index;
m.redraw();
@@ -127,28 +124,6 @@ class PostStreamState {
return this.loadPromise;
}
- /**
- * Execute a callback when necessary because the scroll position changed.
- *
- * The callback will be called with three arguments:
- * - the "type" of position to jump to ("number" or "index")
- * - the corresponding position
- * - whether scrolling should be animated
- *
- * @param callback
- */
- scrollEffect(callback) {
- if (!this.needsScroll) return;
-
- if (this.locationType === 'number') {
- callback('number', this.number, !this.noAnimationScroll);
- } else {
- callback('index', this.sanitizeIndex(this.index), !this.noAnimationScroll);
- }
-
- this.needsScroll = false;
- }
-
/**
* Clear the stream and load posts near a certain number. Returns a promise.
* If the post with the given number is already loaded, the promise will be