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

View File

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