mirror of
https://github.com/flarum/framework.git
synced 2025-05-01 09:04:04 +08:00
A bit more cleanup, UI bugfixes
This commit is contained in:
parent
92b62e7ab6
commit
af55a13c61
@ -206,7 +206,7 @@ export default class PostStream extends Component {
|
|||||||
const threeQuartersVisible = visibleTop / height < 0.75;
|
const threeQuartersVisible = visibleTop / height < 0.75;
|
||||||
const coversQuarterOfViewport = (height - visibleTop) / viewportHeight > 0.25;
|
const coversQuarterOfViewport = (height - visibleTop) / viewportHeight > 0.25;
|
||||||
if (index === undefined && (threeQuartersVisible || coversQuarterOfViewport)) {
|
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
|
// If this item has a time associated with it, then set the
|
||||||
// scrollbar's current period to a formatted version of this time.
|
// scrollbar's current period to a formatted version of this time.
|
||||||
const time = $this.data('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(() => {
|
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);
|
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);
|
$(window).scrollTop(scroll);
|
||||||
this.calculatePosition();
|
this.calculatePosition();
|
||||||
this.updateScrubber();
|
|
||||||
this.state.paused = false;
|
this.state.paused = false;
|
||||||
m.redraw();
|
m.redraw();
|
||||||
});
|
});
|
||||||
|
@ -17,21 +17,21 @@ export default class PostStreamScrubber extends Component {
|
|||||||
this.state = this.props.state;
|
this.state = this.props.state;
|
||||||
this.handlers = {};
|
this.handlers = {};
|
||||||
|
|
||||||
this.scrollListener = new ScrollListener(this.updateScrubberValues.bind(this));
|
this.scrollListener = new ScrollListener(this.updateScrubberValues.bind(this, { fromScroll: true, forceHeightChange: true }));
|
||||||
}
|
}
|
||||||
|
|
||||||
view() {
|
view() {
|
||||||
const index = this.state.index;
|
|
||||||
const count = this.state.count();
|
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, {
|
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>,
|
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) {
|
function styleUnread(element, isInitialized, context) {
|
||||||
const $element = $(element);
|
const $element = $(element);
|
||||||
const newStyle = {
|
const newStyle = {
|
||||||
@ -47,15 +47,7 @@ export default class PostStreamScrubber extends Component {
|
|||||||
|
|
||||||
context.oldStyle = newStyle;
|
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'];
|
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);
|
if (this.props.className) classNames.push(this.props.className);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -71,15 +63,15 @@ export default class PostStreamScrubber extends Component {
|
|||||||
</a>
|
</a>
|
||||||
|
|
||||||
<div className="Scrubber-scrollbar">
|
<div className="Scrubber-scrollbar">
|
||||||
<div className="Scrubber-before" style={{ height: beforeHeight + '%' }} />
|
<div className="Scrubber-before" />
|
||||||
<div className="Scrubber-handle" style={{ height: handleHeight + '%' }}>
|
<div className="Scrubber-handle">
|
||||||
<div className="Scrubber-bar" />
|
<div className="Scrubber-bar" />
|
||||||
<div className="Scrubber-info">
|
<div className="Scrubber-info">
|
||||||
<strong>{viewing}</strong>
|
<strong>{viewing}</strong>
|
||||||
<span className="Scrubber-description">{this.state.description}</span>
|
<span className="Scrubber-description">{this.state.description}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="Scrubber-after" style={{ height: afterHeight + '%' }} />
|
<div className="Scrubber-after" />
|
||||||
|
|
||||||
<div className="Scrubber-unread" config={styleUnread}>
|
<div className="Scrubber-unread" config={styleUnread}>
|
||||||
{app.translator.trans('core.forum.post_scrubber.unread_text', { count: unreadCount })}
|
{app.translator.trans('core.forum.post_scrubber.unread_text', { count: unreadCount })}
|
||||||
@ -130,6 +122,7 @@ export default class PostStreamScrubber extends Component {
|
|||||||
*/
|
*/
|
||||||
goToFirst() {
|
goToFirst() {
|
||||||
this.state.goToFirst();
|
this.state.goToFirst();
|
||||||
|
this.updateScrubberValues({ animate: true, forceHeightChange: true });
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -137,10 +130,12 @@ export default class PostStreamScrubber extends Component {
|
|||||||
*/
|
*/
|
||||||
goToLast() {
|
goToLast() {
|
||||||
this.state.goToLast();
|
this.state.goToLast();
|
||||||
|
this.updateScrubberValues({ animate: true, forceHeightChange: true });
|
||||||
}
|
}
|
||||||
|
|
||||||
config(isInitialized, context) {
|
config(isInitialized, context) {
|
||||||
if (isInitialized) return;
|
if (isInitialized) return;
|
||||||
|
this.state.loadPromise.then(() => this.updateScrubberValues({ animate: true }));
|
||||||
|
|
||||||
context.onunload = this.ondestroy.bind(this);
|
context.onunload = this.ondestroy.bind(this);
|
||||||
|
|
||||||
@ -248,6 +243,7 @@ export default class PostStreamScrubber extends Component {
|
|||||||
// content that we want to load those posts.
|
// content that we want to load those posts.
|
||||||
const intIndex = Math.floor(this.state.index);
|
const intIndex = Math.floor(this.state.index);
|
||||||
this.state.goToIndex(intIndex);
|
this.state.goToIndex(intIndex);
|
||||||
|
this.updateScrubberValues({ animate: true, forceHeightChange: true });
|
||||||
}
|
}
|
||||||
|
|
||||||
onclick(e) {
|
onclick(e) {
|
||||||
@ -269,28 +265,53 @@ export default class PostStreamScrubber extends Component {
|
|||||||
let offsetIndex = offsetPercent / this.percentPerPost().index;
|
let offsetIndex = offsetPercent / this.percentPerPost().index;
|
||||||
offsetIndex = Math.max(0, Math.min(this.state.count() - 1, offsetIndex));
|
offsetIndex = Math.max(0, Math.min(this.state.count() - 1, offsetIndex));
|
||||||
this.state.goToIndex(Math.floor(offsetIndex));
|
this.state.goToIndex(Math.floor(offsetIndex));
|
||||||
|
this.updateScrubberValues({ animate: true, forceHeightChange: true });
|
||||||
|
|
||||||
this.$().removeClass('open');
|
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 index = this.state.index;
|
||||||
const count = this.state.count();
|
const count = this.state.count();
|
||||||
const visible = this.state.visible() || 1;
|
const visible = this.state.visible() || 1;
|
||||||
const percentPerPost = this.percentPerPost();
|
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 = {};
|
const heights = {};
|
||||||
heights.before = Math.max(0, percentPerPost.index * Math.min(index, count - visible));
|
heights.before = Math.max(0, percentPerPost.index * Math.min(index, count - visible));
|
||||||
heights.handle = Math.min(100 - heights.before, percentPerPost.visible * visible);
|
heights.handle = Math.min(100 - heights.before, percentPerPost.visible * visible);
|
||||||
heights.after = 100 - heights.before - heights.handle;
|
heights.after = 100 - heights.before - heights.handle;
|
||||||
|
|
||||||
for (const part in heights) {
|
console.log(heights.after);
|
||||||
this.$(`.Scrubber-${part}`).css('height', heights[part] + '%');
|
|
||||||
|
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) {
|
loadPage(start, end, backwards) {
|
||||||
console.log('loadPage');
|
console.log('loadPage');
|
||||||
|
m.redraw();
|
||||||
|
|
||||||
this.loadPageTimeouts[start] = setTimeout(
|
this.loadPageTimeouts[start] = setTimeout(
|
||||||
() => {
|
() => {
|
||||||
|
@ -7,7 +7,8 @@
|
|||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
margin-right: 2px;
|
margin-right: 2px;
|
||||||
}
|
}
|
||||||
&:hover, &:focus {
|
&:hover,
|
||||||
|
&:focus {
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
color: @link-color;
|
color: @link-color;
|
||||||
}
|
}
|
||||||
@ -19,22 +20,20 @@
|
|||||||
min-height: 50px; // JavaScript sets a max-height
|
min-height: 50px; // JavaScript sets a max-height
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
.Scrubber-before, .Scrubber-after {
|
.Scrubber-before,
|
||||||
|
.Scrubber-after {
|
||||||
border-left: 1px solid @control-bg;
|
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 {
|
.Scrubber-unread {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
border-left: 1px solid lighten(@muted-color, 10%);
|
border-left: 1px solid lighten(@muted-color, 10%);
|
||||||
width: 100%;
|
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;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
color: @muted-color;
|
color: @muted-color;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user