mirror of
https://github.com/flarum/framework.git
synced 2024-11-25 09:41:49 +08:00
Convert to state
This commit is contained in:
parent
b965a82bb1
commit
4464ab156f
|
@ -1,4 +1,5 @@
|
||||||
import Component from '../../common/Component';
|
import Component from '../../common/Component';
|
||||||
|
import Button from '../../common/components/Button';
|
||||||
import icon from '../../common/helpers/icon';
|
import icon from '../../common/helpers/icon';
|
||||||
import formatNumber from '../../common/utils/formatNumber';
|
import formatNumber from '../../common/utils/formatNumber';
|
||||||
import ScrollListener from '../../common/utils/ScrollListener';
|
import ScrollListener from '../../common/utils/ScrollListener';
|
||||||
|
@ -19,6 +20,8 @@ export default class PostStreamScrubber extends Component {
|
||||||
this.stream = this.attrs.stream;
|
this.stream = this.attrs.stream;
|
||||||
this.handlers = {};
|
this.handlers = {};
|
||||||
|
|
||||||
|
this.pendingMoveIndex = null;
|
||||||
|
|
||||||
this.scrollListener = new ScrollListener(this.updateScrubberValues.bind(this, { fromScroll: true, forceHeightChange: true }));
|
this.scrollListener = new ScrollListener(this.updateScrubberValues.bind(this, { fromScroll: true, forceHeightChange: true }));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,9 +35,9 @@ export default class PostStreamScrubber extends Component {
|
||||||
});
|
});
|
||||||
|
|
||||||
const index = this.stream.index;
|
const index = this.stream.index;
|
||||||
|
const previousIndex = this.stream.previousIndex;
|
||||||
|
|
||||||
const showBackButton =
|
const showBackButton = previousIndex > count / 20 && previousIndex < count - count / 20 && 100 * Math.abs((index - previousIndex) / count) > 25;
|
||||||
this.lastPosition > count / 20 && this.lastPosition < count - count / 20 && 100 * Math.abs((index - this.lastPosition) / count) > 25;
|
|
||||||
|
|
||||||
const unreadCount = this.stream.discussion.unreadCount();
|
const unreadCount = this.stream.discussion.unreadCount();
|
||||||
const unreadPercent = count ? Math.min(count - index, unreadCount) / count : 0;
|
const unreadPercent = count ? Math.min(count - index, unreadCount) / count : 0;
|
||||||
|
@ -57,6 +60,8 @@ export default class PostStreamScrubber extends Component {
|
||||||
const classNames = ['PostStreamScrubber', 'Dropdown'];
|
const classNames = ['PostStreamScrubber', 'Dropdown'];
|
||||||
if (this.attrs.className) classNames.push(this.attrs.className);
|
if (this.attrs.className) classNames.push(this.attrs.className);
|
||||||
|
|
||||||
|
console.log(showBackButton);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={classNames.join(' ')}>
|
<div className={classNames.join(' ')}>
|
||||||
<button className="Button Dropdown-toggle" data-toggle="dropdown">
|
<button className="Button Dropdown-toggle" data-toggle="dropdown">
|
||||||
|
@ -70,7 +75,11 @@ export default class PostStreamScrubber extends Component {
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
<div className="Scrubber-scrollbar">
|
<div className="Scrubber-scrollbar">
|
||||||
{showBackButton ? this.backButton() : ''}
|
{showBackButton ? (
|
||||||
|
<a style={'top: ' + this.percentPerPost().index * this.stream.previousIndex + '%'} className="Scrubber-back" onclick={this.returnToLastPosition.bind(this)} title={app.translator.trans('core.forum.post_scrubber.back_title')}>
|
||||||
|
{icon('fas fa-chevron-left')}
|
||||||
|
</a>
|
||||||
|
) : ''}
|
||||||
<div className="Scrubber-before" />
|
<div className="Scrubber-before" />
|
||||||
<div className="Scrubber-handle">
|
<div className="Scrubber-handle">
|
||||||
<div className="Scrubber-bar" />
|
<div className="Scrubber-bar" />
|
||||||
|
@ -95,22 +104,11 @@ export default class PostStreamScrubber extends Component {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
backButton() {
|
|
||||||
return (
|
|
||||||
<div style={'top: ' + this.percentPerPost().index * this.lastPosition + '%'} className="Scrubber-back">
|
|
||||||
{icon('fas fa-minus')}
|
|
||||||
<button className="Button Button--primary" onclick={this.returnToLastPosition.bind(this)}>
|
|
||||||
{app.translator.trans('core.forum.post_scrubber.back')}
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
returnToLastPosition(e) {
|
returnToLastPosition(e) {
|
||||||
// Don't fire the scrubber click event as well
|
// Don't fire the scrubber click event as well
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
|
|
||||||
this.stream.goToIndex(Math.floor(this.lastPosition));
|
this.stream.goToIndex(Math.floor(this.stream.previousIndex));
|
||||||
this.updateScrubberValues({ animate: true });
|
this.updateScrubberValues({ animate: true });
|
||||||
|
|
||||||
this.$().removeClass('open');
|
this.$().removeClass('open');
|
||||||
|
@ -184,7 +182,7 @@ export default class PostStreamScrubber extends Component {
|
||||||
* @param {Boolean} animate
|
* @param {Boolean} animate
|
||||||
*/
|
*/
|
||||||
updateScrubberValues(options = {}) {
|
updateScrubberValues(options = {}) {
|
||||||
const index = this.stream.index;
|
const index = this.pendingMoveIndex || this.stream.index;
|
||||||
const count = this.stream.count();
|
const count = this.stream.count();
|
||||||
const visible = this.stream.visible || 1;
|
const visible = this.stream.visible || 1;
|
||||||
const percentPerPost = this.percentPerPost();
|
const percentPerPost = this.percentPerPost();
|
||||||
|
@ -226,7 +224,6 @@ export default class PostStreamScrubber extends Component {
|
||||||
* Go to the first post in the discussion.
|
* Go to the first post in the discussion.
|
||||||
*/
|
*/
|
||||||
goToFirst() {
|
goToFirst() {
|
||||||
this.lastPosition = this.stream.index;
|
|
||||||
this.stream.goToFirst();
|
this.stream.goToFirst();
|
||||||
this.updateScrubberValues({ animate: true, forceHeightChange: true });
|
this.updateScrubberValues({ animate: true, forceHeightChange: true });
|
||||||
}
|
}
|
||||||
|
@ -235,7 +232,6 @@ export default class PostStreamScrubber extends Component {
|
||||||
* Go to the last post in the discussion.
|
* Go to the last post in the discussion.
|
||||||
*/
|
*/
|
||||||
goToLast() {
|
goToLast() {
|
||||||
this.lastPosition = this.stream.index;
|
|
||||||
this.stream.goToLast();
|
this.stream.goToLast();
|
||||||
this.updateScrubberValues({ animate: true, forceHeightChange: true });
|
this.updateScrubberValues({ animate: true, forceHeightChange: true });
|
||||||
}
|
}
|
||||||
|
@ -261,7 +257,6 @@ export default class PostStreamScrubber extends Component {
|
||||||
this.mouseStart = e.clientY || e.originalEvent.touches[0].clientY;
|
this.mouseStart = e.clientY || e.originalEvent.touches[0].clientY;
|
||||||
this.indexStart = this.stream.index;
|
this.indexStart = this.stream.index;
|
||||||
this.dragging = true;
|
this.dragging = true;
|
||||||
this.lastPosition = this.stream.index;
|
|
||||||
$('body').css('cursor', 'move');
|
$('body').css('cursor', 'move');
|
||||||
this.$().toggleClass('dragging', this.dragging);
|
this.$().toggleClass('dragging', this.dragging);
|
||||||
}
|
}
|
||||||
|
@ -278,7 +273,7 @@ export default class PostStreamScrubber extends Component {
|
||||||
const deltaIndex = deltaPercent / this.percentPerPost().index || 0;
|
const deltaIndex = deltaPercent / this.percentPerPost().index || 0;
|
||||||
const newIndex = Math.min(this.indexStart + deltaIndex, this.stream.count() - 1);
|
const newIndex = Math.min(this.indexStart + deltaIndex, this.stream.count() - 1);
|
||||||
|
|
||||||
this.stream.index = Math.max(0, newIndex);
|
this.pendingMoveIndex = Math.max(0, newIndex);
|
||||||
this.updateScrubberValues();
|
this.updateScrubberValues();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -295,8 +290,9 @@ export default class PostStreamScrubber extends Component {
|
||||||
|
|
||||||
// If the index we've landed on is in a gap, then tell the stream-
|
// If the index we've landed on is in a gap, then tell the stream-
|
||||||
// content that we want to load those posts.
|
// content that we want to load those posts.
|
||||||
const intIndex = Math.floor(this.stream.index);
|
const intIndex = Math.floor(this.pendingMoveIndex);
|
||||||
this.stream.goToIndex(intIndex);
|
this.stream.goToIndex(intIndex);
|
||||||
|
this.pendingMoveIndex = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
onclick(e) {
|
onclick(e) {
|
||||||
|
@ -308,7 +304,6 @@ export default class PostStreamScrubber extends Component {
|
||||||
const $scrollbar = this.$('.Scrubber-scrollbar');
|
const $scrollbar = this.$('.Scrubber-scrollbar');
|
||||||
const offsetPixels = (e.pageY || e.originalEvent.touches[0].pageY) - $scrollbar.offset().top + $('body').scrollTop();
|
const offsetPixels = (e.pageY || e.originalEvent.touches[0].pageY) - $scrollbar.offset().top + $('body').scrollTop();
|
||||||
let offsetPercent = (offsetPixels / $scrollbar.outerHeight()) * 100;
|
let offsetPercent = (offsetPixels / $scrollbar.outerHeight()) * 100;
|
||||||
this.lastPosition = this.stream.index;
|
|
||||||
|
|
||||||
// 2. We want the handle of the scrollbar to end up centered on the click
|
// 2. We want the handle of the scrollbar to end up centered on the click
|
||||||
// position. Thus, we calculate the height of the handle in percent and
|
// position. Thus, we calculate the height of the handle in percent and
|
||||||
|
|
|
@ -22,6 +22,7 @@ class PostStreamState {
|
||||||
this.pagesLoading = 0;
|
this.pagesLoading = 0;
|
||||||
|
|
||||||
this.index = 0;
|
this.index = 0;
|
||||||
|
this.previousIndex = 0;
|
||||||
this.number = 1;
|
this.number = 1;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -137,6 +138,7 @@ class PostStreamState {
|
||||||
this.needsScroll = true;
|
this.needsScroll = true;
|
||||||
this.targetPost = { index };
|
this.targetPost = { index };
|
||||||
this.animateScroll = !noAnimation;
|
this.animateScroll = !noAnimation;
|
||||||
|
this.previousIndex = (index === this.previousIndex) ? index : this.index;
|
||||||
this.index = index;
|
this.index = index;
|
||||||
|
|
||||||
m.redraw();
|
m.redraw();
|
||||||
|
|
|
@ -24,20 +24,9 @@
|
||||||
}
|
}
|
||||||
.Scrubber-back {
|
.Scrubber-back {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
left: 12.5px;
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
|
color: @muted-color;
|
||||||
.icon {
|
|
||||||
margin-left: -0.35em;
|
|
||||||
color: @muted-color;
|
|
||||||
}
|
|
||||||
|
|
||||||
.Button {
|
|
||||||
padding: 5px;
|
|
||||||
position: absolute;
|
|
||||||
left: 15px;
|
|
||||||
top: -5px;
|
|
||||||
width: initial;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
.Scrubber-unread {
|
.Scrubber-unread {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user