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

Encapsulate a bit more logic in the state

This commit is contained in:
Franz Liedke
2020-07-31 15:41:47 +02:00
parent 57f5ad4893
commit 01384139ef
2 changed files with 39 additions and 20 deletions

View File

@@ -102,20 +102,17 @@ export default class PostStream extends Component {
}
config(isInitialized, context) {
if (this.stream.needsScroll) {
this.stream.needsScroll = false;
const locationType = this.stream.locationType;
if (locationType == 'number') {
this.scrollToNumber(this.stream.number, this.stream.noAnimationScroll);
} else if (locationType == 'index') {
const index = this.stream.sanitizeIndex(this.stream.index);
const backwards = index == this.stream.count() - 1;
this.scrollToIndex(index, this.stream.noAnimationScroll, backwards);
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[locationType] = this.stream[locationType];
}
});
if (isInitialized) return;
// This is wrapped in setTimeout due to the following Mithril issue:
// https://github.com/lhorie/mithril.js/issues/637
setTimeout(() => this.scrollListener.start());
@@ -274,28 +271,28 @@ export default class PostStream extends Component {
* Scroll down to a certain post by number and 'flash' it.
*
* @param {Integer} number
* @param {Boolean} noAnimation
* @param {Boolean} animate
* @return {jQuery.Deferred}
*/
scrollToNumber(number, noAnimation) {
scrollToNumber(number, animate) {
const $item = this.$(`.PostStream-item[data-number=${number}]`);
return this.scrollToItem($item, noAnimation).then(this.flashItem.bind(this, $item));
return this.scrollToItem($item, animate).then(this.flashItem.bind(this, $item));
}
/**
* Scroll down to a certain post by index.
*
* @param {Integer} index
* @param {Boolean} noAnimation
* @param {Boolean} animate
* @param {Boolean} bottom Whether or not to scroll to the bottom of the post
* at the given index, instead of the top of it.
* @return {jQuery.Deferred}
*/
scrollToIndex(index, noAnimation, bottom) {
scrollToIndex(index, animate, bottom) {
const $item = this.$(`.PostStream-item[data-index=${index}]`);
return this.scrollToItem($item, noAnimation, true, bottom).then(() => {
return this.scrollToItem($item, animate, true, bottom).then(() => {
if (index == this.stream.count() - 1) {
this.flashItem(this.$('.PostStream-item:last-child'));
}
@@ -306,14 +303,14 @@ export default class PostStream extends Component {
* Scroll down to the given post.
*
* @param {jQuery} $item
* @param {Boolean} noAnimation
* @param {Boolean} animate
* @param {Boolean} force Whether or not to force scrolling to the item, even
* if it is already in the viewport.
* @param {Boolean} bottom Whether or not to scroll to the bottom of the post
* at the given index, instead of the top of it.
* @return {jQuery.Deferred}
*/
scrollToItem($item, noAnimation, force, bottom) {
scrollToItem($item, animate, force, bottom) {
const $container = $('html, body').stop(true);
if ($item.length) {
@@ -328,7 +325,7 @@ export default class PostStream extends Component {
if (force || itemTop < scrollTop || itemBottom > scrollBottom) {
const top = bottom ? itemBottom - $(window).height() + app.composer.computedHeight() : $item.is(':first-child') ? 0 : itemTop;
if (noAnimation) {
if (!animate) {
$container.scrollTop(top);
} else if (top !== scrollTop) {
$container.animate({ scrollTop: top }, 'fast');

View File

@@ -127,6 +127,28 @@ 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