mirror of
https://github.com/flarum/framework.git
synced 2025-03-23 22:45:12 +08:00
A bit more cleanup, UI bugfixes
This commit is contained in:
parent
92b62e7ab6
commit
af55a13c61
js/src/forum
less/forum
@ -206,7 +206,7 @@ export default class PostStream extends Component {
|
||||
const threeQuartersVisible = visibleTop / height < 0.75;
|
||||
const coversQuarterOfViewport = (height - visibleTop) / viewportHeight > 0.25;
|
||||
if (index === undefined && (threeQuartersVisible || coversQuarterOfViewport)) {
|
||||
index = parseFloat($this.data('index')) + visibleTop / height;
|
||||
index = parseFloat($this.data('index')) + (visibleTop / height) * (1 / 0.75);
|
||||
// If this item has a time associated with it, then set the
|
||||
// scrollbar's current period to a formatted version of this time.
|
||||
const time = $this.data('time');
|
||||
@ -343,12 +343,12 @@ export default class PostStream extends Component {
|
||||
}
|
||||
|
||||
return Promise.all([$container.promise(), this.state.loadPromise]).then(() => {
|
||||
const index = $item.data('index');
|
||||
this.state.index = $item.data('index');
|
||||
this.updateScrubber();
|
||||
m.redraw(true);
|
||||
const scroll = index == 0 ? 0 : $(`.PostStream-item[data-index=${$item.data('index')}]`).offset().top - this.getMarginTop();
|
||||
const scroll = this.state.index == 0 ? 0 : $(`.PostStream-item[data-index=${$item.data('index')}]`).offset().top - this.getMarginTop();
|
||||
$(window).scrollTop(scroll);
|
||||
this.calculatePosition();
|
||||
this.updateScrubber();
|
||||
this.state.paused = false;
|
||||
m.redraw();
|
||||
});
|
||||
|
@ -17,21 +17,21 @@ export default class PostStreamScrubber extends Component {
|
||||
this.state = this.props.state;
|
||||
this.handlers = {};
|
||||
|
||||
this.scrollListener = new ScrollListener(this.updateScrubberValues.bind(this));
|
||||
this.scrollListener = new ScrollListener(this.updateScrubberValues.bind(this, { fromScroll: true, forceHeightChange: true }));
|
||||
}
|
||||
|
||||
view() {
|
||||
const index = this.state.index;
|
||||
const count = this.state.count();
|
||||
const visible = this.state.visible() || 1;
|
||||
const unreadCount = this.state.discussion.unreadCount();
|
||||
const unreadPercent = count ? Math.min(count - this.state.index, unreadCount) / count : 0;
|
||||
|
||||
// Index is left blank for performance reasons, it is filled in in updateScubberValues
|
||||
const viewing = app.translator.transChoice('core.forum.post_scrubber.viewing_text', count, {
|
||||
index: <span className="Scrubber-index">{formatNumber(this.state.sanitizeIndex(index + 1))}</span>,
|
||||
index: <span className="Scrubber-index"></span>,
|
||||
count: <span className="Scrubber-count">{formatNumber(count)}</span>,
|
||||
});
|
||||
|
||||
const unreadCount = this.state.discussion.unreadCount();
|
||||
const unreadPercent = count ? Math.min(count - this.state.index, unreadCount) / count : 0;
|
||||
|
||||
function styleUnread(element, isInitialized, context) {
|
||||
const $element = $(element);
|
||||
const newStyle = {
|
||||
@ -47,15 +47,7 @@ export default class PostStreamScrubber extends Component {
|
||||
|
||||
context.oldStyle = newStyle;
|
||||
}
|
||||
|
||||
const percentPerPost = this.percentPerPost();
|
||||
const beforeHeight = Math.max(0, percentPerPost.index * Math.min(index, count - visible));
|
||||
const handleHeight = Math.min(100 - beforeHeight, percentPerPost.visible * visible);
|
||||
const afterHeight = 100 - beforeHeight - handleHeight;
|
||||
|
||||
const classNames = ['PostStreamScrubber', 'Dropdown'];
|
||||
if (this.state.disabled()) classNames.push('disabled');
|
||||
if (this.dragging) classNames.push('dragging');
|
||||
if (this.props.className) classNames.push(this.props.className);
|
||||
|
||||
return (
|
||||
@ -71,15 +63,15 @@ export default class PostStreamScrubber extends Component {
|
||||
</a>
|
||||
|
||||
<div className="Scrubber-scrollbar">
|
||||
<div className="Scrubber-before" style={{ height: beforeHeight + '%' }} />
|
||||
<div className="Scrubber-handle" style={{ height: handleHeight + '%' }}>
|
||||
<div className="Scrubber-before" />
|
||||
<div className="Scrubber-handle">
|
||||
<div className="Scrubber-bar" />
|
||||
<div className="Scrubber-info">
|
||||
<strong>{viewing}</strong>
|
||||
<span className="Scrubber-description">{this.state.description}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className="Scrubber-after" style={{ height: afterHeight + '%' }} />
|
||||
<div className="Scrubber-after" />
|
||||
|
||||
<div className="Scrubber-unread" config={styleUnread}>
|
||||
{app.translator.trans('core.forum.post_scrubber.unread_text', { count: unreadCount })}
|
||||
@ -130,6 +122,7 @@ export default class PostStreamScrubber extends Component {
|
||||
*/
|
||||
goToFirst() {
|
||||
this.state.goToFirst();
|
||||
this.updateScrubberValues({ animate: true, forceHeightChange: true });
|
||||
}
|
||||
|
||||
/**
|
||||
@ -137,10 +130,12 @@ export default class PostStreamScrubber extends Component {
|
||||
*/
|
||||
goToLast() {
|
||||
this.state.goToLast();
|
||||
this.updateScrubberValues({ animate: true, forceHeightChange: true });
|
||||
}
|
||||
|
||||
config(isInitialized, context) {
|
||||
if (isInitialized) return;
|
||||
this.state.loadPromise.then(() => this.updateScrubberValues({ animate: true }));
|
||||
|
||||
context.onunload = this.ondestroy.bind(this);
|
||||
|
||||
@ -248,6 +243,7 @@ export default class PostStreamScrubber extends Component {
|
||||
// content that we want to load those posts.
|
||||
const intIndex = Math.floor(this.state.index);
|
||||
this.state.goToIndex(intIndex);
|
||||
this.updateScrubberValues({ animate: true, forceHeightChange: true });
|
||||
}
|
||||
|
||||
onclick(e) {
|
||||
@ -269,28 +265,53 @@ export default class PostStreamScrubber extends Component {
|
||||
let offsetIndex = offsetPercent / this.percentPerPost().index;
|
||||
offsetIndex = Math.max(0, Math.min(this.state.count() - 1, offsetIndex));
|
||||
this.state.goToIndex(Math.floor(offsetIndex));
|
||||
this.updateScrubberValues({ animate: true, forceHeightChange: true });
|
||||
|
||||
this.$().removeClass('open');
|
||||
}
|
||||
|
||||
updateScrubberValues() {
|
||||
console.log(this.dragging);
|
||||
/**
|
||||
* Update the scrollbar's position to reflect the current values of the
|
||||
* index/visible properties.
|
||||
*
|
||||
* @param {Boolean} animate
|
||||
*/
|
||||
updateScrubberValues(options = {}) {
|
||||
const index = this.state.index;
|
||||
const count = this.state.count();
|
||||
const visible = this.state.visible() || 1;
|
||||
const percentPerPost = this.percentPerPost();
|
||||
|
||||
this.$(`.Scrubber-index`).html(formatNumber(this.state.sanitizeIndex(index + 1)));
|
||||
const $scrubber = this.$();
|
||||
$scrubber.find(`.Scrubber-index`).html(formatNumber(this.state.sanitizeIndex(index + 1)));
|
||||
|
||||
const heights = {};
|
||||
heights.before = Math.max(0, percentPerPost.index * Math.min(index, count - visible));
|
||||
heights.handle = Math.min(100 - heights.before, percentPerPost.visible * visible);
|
||||
heights.after = 100 - heights.before - heights.handle;
|
||||
|
||||
for (const part in heights) {
|
||||
this.$(`.Scrubber-${part}`).css('height', heights[part] + '%');
|
||||
console.log(heights.after);
|
||||
|
||||
if (!(options.fromScroll && this.state.paused) && (!this.adjustingHeight || options.forceHeightChange)) {
|
||||
const func = options.animate ? 'animate' : 'css';
|
||||
this.adjustingHeight = true;
|
||||
const animationPromises = [];
|
||||
for (const part in heights) {
|
||||
const $part = $scrubber.find(`.Scrubber-${part}`);
|
||||
animationPromises.push(
|
||||
$part
|
||||
.stop(true, true)
|
||||
[func]({ height: heights[part] + '%' }, 'fast')
|
||||
.promise()
|
||||
);
|
||||
|
||||
// jQuery likes to put overflow:hidden, but because the scrollbar handle
|
||||
// has a negative margin-left, we need to override.
|
||||
if (func === 'animate') $part.css('overflow', 'visible');
|
||||
}
|
||||
Promise.all(animationPromises).then(() => (this.adjustingHeight = false));
|
||||
}
|
||||
|
||||
this.$().toggleClass('disabled', this.state.disabled());
|
||||
$scrubber.toggleClass('disabled', this.state.disabled());
|
||||
}
|
||||
}
|
||||
|
@ -234,6 +234,7 @@ class PostStreamState {
|
||||
*/
|
||||
loadPage(start, end, backwards) {
|
||||
console.log('loadPage');
|
||||
m.redraw();
|
||||
|
||||
this.loadPageTimeouts[start] = setTimeout(
|
||||
() => {
|
||||
|
@ -7,7 +7,8 @@
|
||||
font-size: 14px;
|
||||
margin-right: 2px;
|
||||
}
|
||||
&:hover, &:focus {
|
||||
&:hover,
|
||||
&:focus {
|
||||
text-decoration: none;
|
||||
color: @link-color;
|
||||
}
|
||||
@ -19,22 +20,20 @@
|
||||
min-height: 50px; // JavaScript sets a max-height
|
||||
position: relative;
|
||||
}
|
||||
.Scrubber-before, .Scrubber-after {
|
||||
.Scrubber-before,
|
||||
.Scrubber-after {
|
||||
border-left: 1px solid @control-bg;
|
||||
transition: height 0.15s linear;
|
||||
}
|
||||
.Scrubber-handle {
|
||||
border-left: 1px solid @control-bg;
|
||||
transition: height 0.25s ease-in;
|
||||
}
|
||||
.dragging .Scrubber-before, .dragging .Scrubber-after, .dragging .Scrubber-handle {
|
||||
transition: none;
|
||||
}
|
||||
.Scrubber-unread {
|
||||
position: absolute;
|
||||
border-left: 1px solid lighten(@muted-color, 10%);
|
||||
width: 100%;
|
||||
background-image: linear-gradient(to right, @control-bg, fade(@control-bg, 0) 10px, fade(@control-bg, 0));
|
||||
background-image: linear-gradient(
|
||||
to right,
|
||||
@control-bg,
|
||||
fade(@control-bg, 0) 10px,
|
||||
fade(@control-bg, 0)
|
||||
);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
color: @muted-color;
|
||||
|
Loading…
x
Reference in New Issue
Block a user