1
0
mirror of https://github.com/flarum/core.git synced 2025-08-07 08:56:38 +02:00

Start decoupling scrolling from state

This commit is contained in:
Franz Liedke
2020-07-31 22:43:02 +02:00
parent e8394e4a1d
commit 6f6a09d7c4
3 changed files with 34 additions and 36 deletions

View File

@@ -109,7 +109,12 @@ export default class DiscussionPage extends Page {
<ul>{listItems(this.sidebarItems().toArray())}</ul>
</nav>
<div className="DiscussionPage-stream">
{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),
})}
</div>
</div>,
]

View File

@@ -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.

View File

@@ -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