mirror of
https://github.com/FrankerFaceZ/FrankerFaceZ.git
synced 2025-07-30 06:28:31 +00:00
Allow smooth scrolling animated chat (#452)
* Allow smooth scrolling animated chat * update to use requestAnimationFrame
This commit is contained in:
parent
5626a3c389
commit
be1e1bfd47
1 changed files with 90 additions and 2 deletions
|
@ -45,6 +45,23 @@ export default class Scroller extends Module {
|
|||
]
|
||||
}
|
||||
});
|
||||
|
||||
this.settings.add('chat.scroller.smooth-scroll', {
|
||||
default: 0,
|
||||
ui: {
|
||||
path: 'Chat > Behavior >> General',
|
||||
title: 'Smooth Scrolling',
|
||||
description: 'Animates new chat messages into view. Will speed up if necessary to keep up with chat.',
|
||||
component: 'setting-select-box',
|
||||
data: [
|
||||
{value: 0, title: 'Disabled'},
|
||||
{value: 1, title: 'Slow'},
|
||||
{value: 2, title: 'Medium'},
|
||||
{value: 3, title: 'Fast'},
|
||||
{value: 4, title: 'Very Fast'}
|
||||
]
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
onEnable() {
|
||||
|
@ -64,6 +81,15 @@ export default class Scroller extends Module {
|
|||
}
|
||||
});
|
||||
|
||||
this.smoothScroll = this.chat.context.get('chat.scroller.smooth-scroll');
|
||||
this.chat.context.on('changed:chat.scroller.smooth-scroll', val => {
|
||||
this.smoothScroll = val;
|
||||
|
||||
for(const inst of this.ChatScroller.instances) {
|
||||
inst.ffzSetSmoothScroll(val);
|
||||
}
|
||||
});
|
||||
|
||||
this.ChatScroller.ready((cls, instances) => {
|
||||
const t = this,
|
||||
old_catch = cls.prototype.componentDidCatch,
|
||||
|
@ -223,6 +249,56 @@ export default class Scroller extends Module {
|
|||
//this.ffzHideFrozen();
|
||||
}
|
||||
|
||||
cls.prototype.smoothScrollBottom = function() {
|
||||
if(this.state.ffzSmoothAnimation){
|
||||
cancelAnimationFrame(this.state.ffzSmoothAnimation);
|
||||
}
|
||||
this.isScrollingToBottom = true;
|
||||
// Step setting value is # pixels to scroll per 10ms.
|
||||
// 1 is pretty slow, 2 medium, 3 fast, 4 very fast.
|
||||
let step = this.ffz_smooth_scroll;
|
||||
const scrollContent = this.scroll.scrollContent;
|
||||
const targetTop = scrollContent.scrollHeight - scrollContent.clientHeight;
|
||||
const difference = targetTop - scrollContent.scrollTop;
|
||||
|
||||
// If we are falling behind speed us up
|
||||
if (difference > scrollContent.clientHeight) {
|
||||
// we are a full scroll away, just jump there
|
||||
step = difference;
|
||||
} else if (difference > 200) {
|
||||
// we are starting to fall behind, speed it up a bit
|
||||
step += step * parseInt(difference / 200, 10);
|
||||
}
|
||||
let prevTime = Date.now();
|
||||
const smoothAnimation = () => {
|
||||
if(this.state.ffzFrozen) {
|
||||
this.isScrollingToBottom = false;
|
||||
return;
|
||||
}
|
||||
// See how much time has passed to get a step based off the delta
|
||||
const currentTime = Date.now();
|
||||
const delta = currentTime - prevTime;
|
||||
const currentStep = step * (delta / 10);
|
||||
// we need to move at least one full pixel for scrollTop to do anything in this delta.
|
||||
if (currentStep >= 1) {
|
||||
prevTime = currentTime;
|
||||
if (scrollContent.scrollTop < (scrollContent.scrollHeight - scrollContent.clientHeight)) {
|
||||
scrollContent.scrollTop += currentStep;
|
||||
this.state.ffzSmoothAnimation = requestAnimationFrame(smoothAnimation);
|
||||
} else {
|
||||
scrollContent.scrollTop = scrollContent.scrollHeight - scrollContent.clientHeight;
|
||||
this.isScrollingToBottom = false;
|
||||
}
|
||||
} else {
|
||||
// the frame happened so quick since last update we didn't move a full pixel yet.
|
||||
// should only be possible if the FPS of a browser went over 60fps.
|
||||
this.state.ffzSmoothAnimation = requestAnimationFrame(smoothAnimation);
|
||||
}
|
||||
|
||||
}
|
||||
smoothAnimation();
|
||||
}
|
||||
|
||||
|
||||
cls.prototype.ffzInstallHandler = function() {
|
||||
if ( this._ffz_handleScroll )
|
||||
|
@ -231,8 +307,13 @@ export default class Scroller extends Module {
|
|||
const t = this;
|
||||
this._old_scroll = this.scrollToBottom;
|
||||
this.scrollToBottom = function() {
|
||||
if ( ! this.ffz_freeze_enabled || ! this.state.ffzFrozen )
|
||||
return this._old_scroll();
|
||||
if ( ! this.ffz_freeze_enabled || ! this.state.ffzFrozen ) {
|
||||
if (this.ffz_smooth_scroll !== 0) {
|
||||
this.smoothScrollBottom();
|
||||
} else {
|
||||
this._old_scroll();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this._ffz_handleScroll = this.handleScrollEvent;
|
||||
|
@ -394,6 +475,11 @@ export default class Scroller extends Module {
|
|||
}
|
||||
|
||||
|
||||
cls.prototype.ffzSetSmoothScroll = function(value) {
|
||||
this.ffz_smooth_scroll = value;
|
||||
}
|
||||
|
||||
|
||||
for(const inst of instances)
|
||||
this.onMount(inst);
|
||||
});
|
||||
|
@ -420,6 +506,8 @@ export default class Scroller extends Module {
|
|||
|
||||
if ( this.freeze !== 0 )
|
||||
inst.ffzEnableFreeze();
|
||||
|
||||
inst.ffzSetSmoothScroll(this.smoothScroll);
|
||||
}
|
||||
|
||||
onUnmount(inst) { // eslint-disable-line class-methods-use-this
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue