Minor cleanup of PostStreamState methods

This commit is contained in:
Alexander Skvortsov
2020-07-08 21:11:47 -04:00
committed by Franz Liedke
parent 5ef4de75d1
commit 92b62e7ab6
3 changed files with 131 additions and 139 deletions

View File

@ -349,7 +349,7 @@ export default class PostStream extends Component {
$(window).scrollTop(scroll); $(window).scrollTop(scroll);
this.calculatePosition(); this.calculatePosition();
this.updateScrubber(); this.updateScrubber();
this.state.unpause(); this.state.paused = false;
m.redraw(); m.redraw();
}); });
} }

View File

@ -54,7 +54,7 @@ export default class PostStreamScrubber extends Component {
const afterHeight = 100 - beforeHeight - handleHeight; const afterHeight = 100 - beforeHeight - handleHeight;
const classNames = ['PostStreamScrubber', 'Dropdown']; const classNames = ['PostStreamScrubber', 'Dropdown'];
if (this.state.allVisible()) classNames.push('disabled'); if (this.state.disabled()) classNames.push('disabled');
if (this.dragging) classNames.push('dragging'); if (this.dragging) classNames.push('dragging');
if (this.props.className) classNames.push(this.props.className); if (this.props.className) classNames.push(this.props.className);
@ -291,6 +291,6 @@ export default class PostStreamScrubber extends Component {
this.$(`.Scrubber-${part}`).css('height', heights[part] + '%'); this.$(`.Scrubber-${part}`).css('height', heights[part] + '%');
} }
this.$().toggleClass('disabled', this.state.allVisible()); this.$().toggleClass('disabled', this.state.disabled());
} }
} }

View File

@ -41,6 +41,38 @@ class PostStreamState {
this.show(includedPosts); this.show(includedPosts);
} }
/**
* Update the stream so that it loads and includes the latest posts in the
* discussion, if the end is being viewed.
*
* @public
*/
update() {
if (!this.viewingEnd()) return m.deferred().resolve().promise;
this.visibleEnd = this.count();
return this.loadRange(this.visibleStart, this.visibleEnd);
}
/**
* Load and scroll up to the first post in the discussion.
*
* @return {Promise}
*/
goToFirst() {
return this.goToIndex(0);
}
/**
* Load and scroll down to the last post in the discussion.
*
* @return {Promise}
*/
goToLast() {
return this.goToIndex(this.count() - 1);
}
/** /**
* Load and scroll to a post with a certain number. * Load and scroll to a post with a certain number.
* *
@ -100,112 +132,49 @@ class PostStreamState {
} }
/** /**
* Load and scroll up to the first post in the discussion. * 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
* resolved immediately.
* *
* @param {Integer} number
* @return {Promise} * @return {Promise}
*/ */
goToFirst() { loadNearNumber(number) {
return this.goToIndex(0); console.log('loadNearNumber', number);
if (this.posts().some((post) => post && Number(post.number()) === Number(number))) {
return m.deferred().resolve().promise;
}
this.reset();
return app.store
.find('posts', {
filter: { discussion: this.discussion.id() },
page: { near: number },
})
.then(this.show.bind(this));
} }
/** /**
* Load and scroll down to the last post in the discussion. * Clear the stream and load posts near a certain index. A page of posts
* * surrounding the given index will be loaded. Returns a promise. If the given
* @return {Promise} * index is already loaded, the promise will be resolved immediately.
*/
goToLast() {
return this.goToIndex(this.count() - 1);
}
/**
* Set up the stream with the given array of posts.
*
* @param {Post[]} posts
*/
show(posts) {
this.visibleStart = posts.length ? this.discussion.postIds().indexOf(posts[0].id()) : 0;
this.visibleEnd = this.sanitizeIndex(this.visibleStart + posts.length);
}
/**
* Reset the stream so that a specific range of posts is displayed. If a range
* is not specified, the first page of posts will be displayed.
*
* @param {Integer} [start]
* @param {Integer} [end]
*/
reset(start, end) {
this.visibleStart = start || 0;
this.visibleEnd = this.sanitizeIndex(end || this.constructor.loadCount);
}
/**
* Get the visible page of posts.
*
* @return {Post[]}
*/
posts() {
return this.discussion
.postIds()
.slice(this.visibleStart, this.visibleEnd)
.map((id) => {
const post = app.store.getById('posts', id);
return post && post.discussion() && typeof post.canEdit() !== 'undefined' ? post : null;
});
}
/**
* Get the total number of posts in the discussion.
*
* @return {Integer}
*/
count() {
return this.discussion.postIds().length;
}
/**
* Check whether or not the scrubber should be disabled, i.e. if all of the
* posts are visible in the viewport.
*
* @return {Boolean}
*/
allVisible() {
return this.visible() >= this.count();
}
/**
* Are we currently viewing the end of the discussion?
*
* @return {boolean}
*/
viewingEnd() {
return this.visibleEnd === this.count();
}
/**
* Make sure that the given index is not outside of the possible range of
* indexes in the discussion.
* *
* @param {Integer} index * @param {Integer} index
* @protected * @return {Promise}
*/ */
sanitizeIndex(index) { loadNearIndex(index) {
return Math.max(0, Math.min(this.count(), Math.floor(index))); console.log('loadNearIndex', index);
if (index >= this.visibleStart && index <= this.visibleEnd) {
return m.deferred().resolve().promise;
} }
/** const start = this.sanitizeIndex(index - this.constructor.loadCount / 2);
* Update the stream so that it loads and includes the latest posts in the const end = start + this.constructor.loadCount;
* discussion, if the end is being viewed.
*
* @public
*/
update() {
if (!this.viewingEnd()) return m.deferred().resolve().promise;
this.visibleEnd = this.count(); this.reset(start, end);
return this.loadRange(this.visibleStart, this.visibleEnd); return this.loadRange(start, end).then(this.show.bind(this));
} }
/** /**
@ -313,56 +282,79 @@ class PostStreamState {
} }
/** /**
* Clear the stream and load posts near a certain number. Returns a promise. * Set up the stream with the given array of posts.
* If the post with the given number is already loaded, the promise will be
* resolved immediately.
* *
* @param {Integer} number * @param {Post[]} posts
* @return {Promise}
*/ */
loadNearNumber(number) { show(posts) {
console.log('loadNearNumber', number); this.visibleStart = posts.length ? this.discussion.postIds().indexOf(posts[0].id()) : 0;
if (this.posts().some((post) => post && Number(post.number()) === Number(number))) { this.visibleEnd = this.sanitizeIndex(this.visibleStart + posts.length);
return m.deferred().resolve().promise;
}
this.reset();
return app.store
.find('posts', {
filter: { discussion: this.discussion.id() },
page: { near: number },
})
.then(this.show.bind(this));
} }
/** /**
* Clear the stream and load posts near a certain index. A page of posts * Reset the stream so that a specific range of posts is displayed. If a range
* surrounding the given index will be loaded. Returns a promise. If the given * is not specified, the first page of posts will be displayed.
* index is already loaded, the promise will be resolved immediately. *
* @param {Integer} [start]
* @param {Integer} [end]
*/
reset(start, end) {
this.visibleStart = start || 0;
this.visibleEnd = this.sanitizeIndex(end || this.constructor.loadCount);
}
/**
* Get the visible page of posts.
*
* @return {Post[]}
*/
posts() {
return this.discussion
.postIds()
.slice(this.visibleStart, this.visibleEnd)
.map((id) => {
const post = app.store.getById('posts', id);
return post && post.discussion() && typeof post.canEdit() !== 'undefined' ? post : null;
});
}
/**
* Get the total number of posts in the discussion.
*
* @return {Integer}
*/
count() {
return this.discussion.postIds().length;
}
/**
* Check whether or not the scrubber should be disabled, i.e. if all of the
* posts are visible in the viewport.
*
* @return {Boolean}
*/
disabled() {
return this.visible() >= this.count();
}
/**
* Are we currently viewing the end of the discussion?
*
* @return {boolean}
*/
viewingEnd() {
return this.visibleEnd === this.count();
}
/**
* Make sure that the given index is not outside of the possible range of
* indexes in the discussion.
* *
* @param {Integer} index * @param {Integer} index
* @return {Promise}
*/ */
loadNearIndex(index) { sanitizeIndex(index) {
console.log('loadNearIndex', index); return Math.max(0, Math.min(this.count(), Math.floor(index)));
if (index >= this.visibleStart && index <= this.visibleEnd) {
return m.deferred().resolve().promise;
}
const start = this.sanitizeIndex(index - this.constructor.loadCount / 2);
const end = start + this.constructor.loadCount;
this.reset(start, end);
return this.loadRange(start, end).then(this.show.bind(this));
}
/**
* Resume the stream's ability to auto-load posts on scroll.
*/
unpause() {
this.paused = false;
} }
} }