mirror of
https://github.com/flarum/core.git
synced 2025-08-11 10:55:47 +02:00
Start decoupling scrolling from state
This commit is contained in:
@@ -109,7 +109,12 @@ export default class DiscussionPage extends Page {
|
|||||||
<ul>{listItems(this.sidebarItems().toArray())}</ul>
|
<ul>{listItems(this.sidebarItems().toArray())}</ul>
|
||||||
</nav>
|
</nav>
|
||||||
<div className="DiscussionPage-stream">
|
<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>
|
||||||
</div>,
|
</div>,
|
||||||
]
|
]
|
||||||
|
@@ -12,6 +12,7 @@ import Button from '../../common/components/Button';
|
|||||||
*
|
*
|
||||||
* - `discussion`
|
* - `discussion`
|
||||||
* - `stream`
|
* - `stream`
|
||||||
|
* - `targetPost`
|
||||||
* - `onPositionChange`
|
* - `onPositionChange`
|
||||||
*/
|
*/
|
||||||
export default class PostStream extends Component {
|
export default class PostStream extends Component {
|
||||||
@@ -102,14 +103,7 @@ export default class PostStream extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
config(isInitialized, context) {
|
config(isInitialized, context) {
|
||||||
this.stream.scrollEffect((type, position, animate) => {
|
this.triggerScroll();
|
||||||
if (type === 'number') {
|
|
||||||
this.scrollToNumber(position, animate);
|
|
||||||
} else if (type === 'index') {
|
|
||||||
const backwards = position === this.stream.count() - 1;
|
|
||||||
this.scrollToIndex(position, animate, backwards);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if (isInitialized) return;
|
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
|
* 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.
|
* in the viewport, and if so, trigger loading the next/previous page.
|
||||||
|
@@ -20,7 +20,6 @@ class PostStreamState {
|
|||||||
this.loadPageTimeouts = {};
|
this.loadPageTimeouts = {};
|
||||||
this.pagesLoading = 0;
|
this.pagesLoading = 0;
|
||||||
|
|
||||||
this.locationType = null;
|
|
||||||
this.index = 0;
|
this.index = 0;
|
||||||
this.number = 1;
|
this.number = 1;
|
||||||
|
|
||||||
@@ -92,9 +91,8 @@ class PostStreamState {
|
|||||||
|
|
||||||
this.loadPromise = this.loadNearNumber(number);
|
this.loadPromise = this.loadNearNumber(number);
|
||||||
|
|
||||||
this.needsScroll = true;
|
this.targetPost = { number };
|
||||||
this.noAnimationScroll = noAnimation;
|
this.noAnimationScroll = noAnimation;
|
||||||
this.locationType = 'number';
|
|
||||||
this.number = number;
|
this.number = number;
|
||||||
|
|
||||||
// In this case, the redraw is only called after the response has been loaded
|
// 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.loadPromise = this.loadNearIndex(index);
|
||||||
|
|
||||||
this.needsScroll = true;
|
this.targetPost = { index };
|
||||||
this.noAnimationScroll = noAnimation;
|
this.noAnimationScroll = noAnimation;
|
||||||
this.locationType = 'index';
|
|
||||||
this.index = index;
|
this.index = index;
|
||||||
|
|
||||||
m.redraw();
|
m.redraw();
|
||||||
@@ -127,28 +124,6 @@ class PostStreamState {
|
|||||||
return this.loadPromise;
|
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.
|
* 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
|
* If the post with the given number is already loaded, the promise will be
|
||||||
|
Reference in New Issue
Block a user