2017-11-14 04:12:10 -05:00
|
|
|
'use strict';
|
|
|
|
|
|
|
|
// ============================================================================
|
|
|
|
// Chat Scroller
|
|
|
|
// ============================================================================
|
|
|
|
|
2018-04-01 18:24:08 -04:00
|
|
|
import {createElement} from 'utilities/dom';
|
2018-03-14 13:58:04 -04:00
|
|
|
import Twilight from 'site';
|
2017-11-14 04:12:10 -05:00
|
|
|
import Module from 'utilities/module';
|
|
|
|
|
|
|
|
export default class Scroller extends Module {
|
|
|
|
constructor(...args) {
|
|
|
|
super(...args);
|
|
|
|
|
|
|
|
this.inject('settings');
|
|
|
|
this.inject('i18n');
|
|
|
|
this.inject('chat');
|
|
|
|
this.inject('site.fine');
|
2018-03-03 16:38:50 -05:00
|
|
|
this.inject('site.web_munch');
|
2017-11-14 04:12:10 -05:00
|
|
|
|
|
|
|
this.ChatScroller = this.fine.define(
|
|
|
|
'chat-scroller',
|
2018-03-14 13:58:04 -04:00
|
|
|
n => n.saveScrollRef && n.handleScrollEvent,
|
|
|
|
Twilight.CHAT_ROUTES
|
2017-11-14 04:12:10 -05:00
|
|
|
);
|
|
|
|
|
|
|
|
this.settings.add('chat.scroller.freeze', {
|
|
|
|
default: 0,
|
|
|
|
ui: {
|
|
|
|
path: 'Chat > Behavior >> General',
|
|
|
|
title: 'Freeze Chat Scrolling',
|
|
|
|
description: 'Automatically stop chat from scrolling when moving the mouse over it or holding a key.',
|
|
|
|
component: 'setting-select-box',
|
|
|
|
data: [
|
|
|
|
{value: 0, title: 'Disabled'},
|
|
|
|
{value: 1, title: 'On Hover'},
|
|
|
|
{value: 2, title: 'When Ctrl is Held'},
|
|
|
|
{value: 3, title: 'When Meta is Held'},
|
|
|
|
{value: 4, title: 'When Alt is Held'},
|
|
|
|
{value: 5, title: 'When Shift is Held'},
|
|
|
|
{value: 6, title: 'Ctrl or Hover'},
|
|
|
|
{value: 7, title: 'Meta or Hover'},
|
|
|
|
{value: 8, title: 'Alt or Hover'},
|
|
|
|
{value: 9, title: 'Shift or Hover'}
|
|
|
|
]
|
|
|
|
}
|
|
|
|
});
|
2018-07-03 18:18:39 -04:00
|
|
|
|
|
|
|
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'}
|
|
|
|
]
|
|
|
|
}
|
|
|
|
});
|
2017-11-14 04:12:10 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
onEnable() {
|
2017-11-28 02:03:59 -05:00
|
|
|
this.on('i18n:update', () => {
|
2017-11-14 04:12:10 -05:00
|
|
|
for(const inst of this.ChatScroller.instances)
|
|
|
|
inst.ffzUpdateText();
|
|
|
|
});
|
|
|
|
|
|
|
|
this.freeze = this.chat.context.get('chat.scroller.freeze');
|
|
|
|
this.chat.context.on('changed:chat.scroller.freeze', val => {
|
|
|
|
this.freeze = val;
|
|
|
|
|
2017-11-15 14:05:58 -05:00
|
|
|
for(const inst of this.ChatScroller.instances) {
|
|
|
|
inst.ffzDisableFreeze();
|
|
|
|
if ( val !== 0 )
|
2017-11-14 04:12:10 -05:00
|
|
|
inst.ffzEnableFreeze();
|
2017-11-15 14:05:58 -05:00
|
|
|
}
|
2017-11-14 04:12:10 -05:00
|
|
|
});
|
|
|
|
|
2018-07-03 18:18:39 -04:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2017-11-14 04:12:10 -05:00
|
|
|
this.ChatScroller.ready((cls, instances) => {
|
2018-03-03 16:38:50 -05:00
|
|
|
const t = this,
|
|
|
|
old_catch = cls.prototype.componentDidCatch,
|
|
|
|
old_render = cls.prototype.render;
|
|
|
|
|
|
|
|
// Try catching errors. With any luck, maybe we can
|
|
|
|
// recover from the error when we re-build?
|
|
|
|
cls.prototype.componentDidCatch = function(err, info) {
|
|
|
|
// Don't log infinitely if stuff gets super screwed up.
|
|
|
|
const errs = this.state.ffz_errors || 0;
|
|
|
|
if ( errs < 100 ) {
|
|
|
|
this.setState({
|
|
|
|
ffz_errors: errs + 1,
|
|
|
|
ffz_total_errors: (this.state.ffz_total_errors||0) + 1
|
|
|
|
});
|
2018-04-11 17:05:31 -04:00
|
|
|
|
|
|
|
t.log.capture(err, {extra: info});
|
2018-03-03 16:38:50 -05:00
|
|
|
t.log.info('Error within Chat', err, info, errs);
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( old_catch )
|
|
|
|
return old_catch.call(this, err, info);
|
|
|
|
}
|
|
|
|
|
|
|
|
cls.prototype.ffzZeroErrors = function() {
|
|
|
|
this.setState({ffz_errors: 0});
|
|
|
|
}
|
|
|
|
|
|
|
|
cls.prototype.render = function() {
|
|
|
|
if ( this.state.ffz_errors > 0 ) {
|
|
|
|
let timer;
|
|
|
|
const auto = this.state.ffz_total_errors < 10,
|
|
|
|
React = t.web_munch.getModule('react'),
|
2018-04-01 18:24:08 -04:00
|
|
|
createElement = React && React.createElement,
|
2018-03-03 16:38:50 -05:00
|
|
|
handler = () => {
|
|
|
|
clearTimeout(timer);
|
|
|
|
this.ffzZeroErrors();
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( auto )
|
|
|
|
timer = setTimeout(handler, 250);
|
|
|
|
|
2018-04-01 18:24:08 -04:00
|
|
|
if ( ! createElement )
|
2018-03-03 16:38:50 -05:00
|
|
|
return null;
|
|
|
|
|
2018-04-01 18:24:08 -04:00
|
|
|
return createElement('div', {
|
2018-03-03 16:38:50 -05:00
|
|
|
className: 'tw-border-l tw-c-background-alt-2 tw-c-text tw-full-width tw-full-height tw-align-items-center tw-flex tw-flex-column tw-justify-content-center tw-relative'
|
|
|
|
}, [
|
2018-04-01 18:24:08 -04:00
|
|
|
createElement('div', {className: 'tw-mg-b-1'}, 'There was an error displaying chat.'),
|
|
|
|
! auto && createElement('button', {
|
2018-03-03 16:38:50 -05:00
|
|
|
className: 'tw-button',
|
|
|
|
onClick: handler
|
2018-04-01 18:24:08 -04:00
|
|
|
}, createElement('span', {className: 'tw-button__text'}, 'Try Again'))
|
2018-03-03 16:38:50 -05:00
|
|
|
]);
|
|
|
|
|
|
|
|
} else
|
|
|
|
return old_render.call(this);
|
|
|
|
}
|
2017-11-14 04:12:10 -05:00
|
|
|
|
|
|
|
cls.prototype.ffzShouldBeFrozen = function(since) {
|
|
|
|
if ( since === undefined )
|
|
|
|
since = Date.now() - this.ffz_last_move;
|
|
|
|
|
|
|
|
const f = t.freeze;
|
|
|
|
|
|
|
|
return ! this.ffz_outside && (
|
|
|
|
(this.ffz_ctrl && (f === 2 || f === 6)) ||
|
|
|
|
(this.ffz_meta && (f === 3 || f === 7)) ||
|
|
|
|
(this.ffz_alt && (f === 4 || f === 8)) ||
|
|
|
|
(this.ffz_shift && (f === 5 || f === 9)) ||
|
|
|
|
(since < 750 && (f === 1 || f > 5))
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
cls.prototype.ffzMaybeUnfreeze = function() {
|
|
|
|
if ( this.ffz_frozen )
|
|
|
|
requestAnimationFrame(() => {
|
|
|
|
if ( this.ffz_frozen && ! this.ffzShouldBeFrozen() )
|
|
|
|
this.ffzUnfreeze();
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
cls.prototype.ffzUpdateText = function() {
|
|
|
|
if ( ! this._ffz_freeze_indicator )
|
|
|
|
return;
|
|
|
|
|
|
|
|
const f = t.freeze,
|
|
|
|
reason = f === 2 ? t.i18n.t('key.ctrl', 'Ctrl Key') :
|
|
|
|
f === 3 ? t.i18n.t('key.meta', 'Meta Key') :
|
2017-11-16 15:54:58 -05:00
|
|
|
f === 4 ? t.i18n.t('key.alt', 'Alt Key') :
|
|
|
|
f === 5 ? t.i18n.t('key.shift', 'Shift Key') :
|
|
|
|
f === 6 ? t.i18n.t('key.ctrl_mouse', 'Ctrl or Mouse') :
|
|
|
|
f === 7 ? t.i18n.t('key.meta_mouse', 'Meta or Mouse') :
|
|
|
|
f === 8 ? t.i18n.t('key.alt_mouse', 'Alt or Mouse') :
|
|
|
|
f === 9 ? t.i18n.t('key.shift_mouse', 'Shift or Mouse') :
|
|
|
|
t.i18n.t('key.mouse', 'Mouse Movement');
|
2017-11-14 04:12:10 -05:00
|
|
|
|
|
|
|
this._ffz_freeze_indicator.firstElementChild.textContent = t.i18n.t(
|
|
|
|
'chat.paused',
|
|
|
|
'(Chat Paused Due to %{reason})',
|
|
|
|
{reason}
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
cls.prototype.ffzShowFrozen = function() {
|
2017-11-16 15:54:58 -05:00
|
|
|
this._ffz_freeze_visible = true;
|
2017-11-14 04:12:10 -05:00
|
|
|
let el = this._ffz_freeze_indicator;
|
|
|
|
if ( ! el ) {
|
2018-02-22 18:38:13 -05:00
|
|
|
const node = t.fine.getChildNode(this);
|
2017-11-14 04:12:10 -05:00
|
|
|
if ( ! node )
|
|
|
|
return;
|
|
|
|
|
2017-12-13 17:35:20 -05:00
|
|
|
node.classList.add('tw-full-height');
|
2017-11-14 04:12:10 -05:00
|
|
|
|
2018-04-01 18:24:08 -04:00
|
|
|
el = this._ffz_freeze_indicator = createElement('div', {
|
2017-12-13 17:35:20 -05:00
|
|
|
className: 'ffz--freeze-indicator chat-list__more-messages-placeholder tw-relative tw-mg-x-2'
|
2018-04-01 18:24:08 -04:00
|
|
|
}, createElement('div', {
|
2017-12-13 17:35:20 -05:00
|
|
|
className: 'chat-list__more-messages tw-bottom-0 tw-full-width tw-align-items-center tw-flex tw-justify-content-center tw-absolute tw-pd-05'
|
2017-11-14 04:12:10 -05:00
|
|
|
}));
|
|
|
|
|
|
|
|
this.ffzUpdateText();
|
|
|
|
node.appendChild(el);
|
|
|
|
|
|
|
|
} else
|
2017-12-13 17:35:20 -05:00
|
|
|
el.classList.remove('tw-hide');
|
2017-11-14 04:12:10 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
cls.prototype.ffzHideFrozen = function() {
|
2017-11-16 15:54:58 -05:00
|
|
|
this._ffz_freeze_visible = false;
|
2017-11-14 04:12:10 -05:00
|
|
|
if ( this._ffz_freeze_indicator )
|
2017-12-13 17:35:20 -05:00
|
|
|
this._ffz_freeze_indicator.classList.add('tw-hide');
|
2017-11-14 04:12:10 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
cls.prototype.ffzFreeze = function() {
|
|
|
|
if ( ! this._ffz_interval )
|
|
|
|
this._ffz_interval = setInterval(() => {
|
|
|
|
if ( ! this.ffzShouldBeFrozen() )
|
2017-11-15 14:48:57 -05:00
|
|
|
this.ffzMaybeUnfreeze();
|
2017-11-14 04:12:10 -05:00
|
|
|
}, 200);
|
|
|
|
|
|
|
|
this.ffz_frozen = true;
|
|
|
|
this.setState({ffzFrozen: true});
|
2017-11-16 15:54:58 -05:00
|
|
|
//this.ffzShowFrozen();
|
2017-11-14 04:12:10 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
cls.prototype.ffzUnfreeze = function() {
|
|
|
|
if ( this._ffz_interval ) {
|
|
|
|
clearInterval(this._ffz_interval);
|
|
|
|
this._ffz_interval = null;
|
|
|
|
}
|
|
|
|
|
|
|
|
this.ffz_frozen = false;
|
|
|
|
this.setState({ffzFrozen: false});
|
|
|
|
if ( this.state.isAutoScrolling )
|
|
|
|
this.scrollToBottom();
|
|
|
|
|
2017-11-16 15:54:58 -05:00
|
|
|
//this.ffzHideFrozen();
|
|
|
|
}
|
|
|
|
|
2018-07-03 18:18:39 -04:00
|
|
|
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();
|
|
|
|
}
|
|
|
|
|
2017-11-16 15:54:58 -05:00
|
|
|
|
|
|
|
cls.prototype.ffzInstallHandler = function() {
|
|
|
|
if ( this._ffz_handleScroll )
|
|
|
|
return;
|
|
|
|
|
|
|
|
const t = this;
|
2018-01-15 20:40:54 -05:00
|
|
|
this._old_scroll = this.scrollToBottom;
|
|
|
|
this.scrollToBottom = function() {
|
2018-07-03 18:18:39 -04:00
|
|
|
if ( ! this.ffz_freeze_enabled || ! this.state.ffzFrozen ) {
|
|
|
|
if (this.ffz_smooth_scroll !== 0) {
|
|
|
|
this.smoothScrollBottom();
|
|
|
|
} else {
|
|
|
|
this._old_scroll();
|
|
|
|
}
|
|
|
|
}
|
2018-01-15 20:40:54 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
this._ffz_handleScroll = this.handleScrollEvent;
|
2017-11-16 15:54:58 -05:00
|
|
|
this.handleScrollEvent = function(e) {
|
|
|
|
// If we're frozen because of FFZ, do not allow a mouse click to update
|
|
|
|
// the auto-scrolling state. That just gets annoying.
|
|
|
|
if ( e.type === 'mousedown' && t.ffz_frozen )
|
|
|
|
return;
|
|
|
|
|
2017-11-22 15:39:38 -05:00
|
|
|
if ( t.scroll && e.type === 'touchmove' ) {
|
|
|
|
t.scroll.scrollContent.scrollHeight - t.scroll.scrollContent.scrollTop - t.scroll.scrollContent.offsetHeight <= 10 ? t.setState({
|
|
|
|
isAutoScrolling: !0
|
|
|
|
}) : t.setState({
|
|
|
|
isAutoScrolling: !1
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2017-11-16 15:54:58 -05:00
|
|
|
return t._ffz_handleScroll(e);
|
|
|
|
}
|
|
|
|
|
|
|
|
const scroller = this.scroll && this.scroll.scrollContent;
|
|
|
|
if ( scroller ) {
|
|
|
|
scroller.removeEventListener('mousedown', this._ffz_handleScroll);
|
|
|
|
scroller.addEventListener('mousedown', this.handleScrollEvent);
|
2017-11-22 15:39:38 -05:00
|
|
|
scroller.addEventListener('touchmove', this.handleScrollEvent);
|
2017-11-16 15:54:58 -05:00
|
|
|
}
|
2017-11-14 04:12:10 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
cls.prototype.ffzEnableFreeze = function() {
|
2018-02-22 18:38:13 -05:00
|
|
|
const node = t.fine.getChildNode(this);
|
2017-11-14 04:12:10 -05:00
|
|
|
if ( ! node || this.ffz_freeze_enabled )
|
|
|
|
return;
|
|
|
|
|
|
|
|
this.ffz_freeze_enabled = true;
|
|
|
|
|
2017-11-15 14:05:58 -05:00
|
|
|
if ( t.freeze > 1 ) {
|
|
|
|
document.body.addEventListener('keydown',
|
|
|
|
this._ffz_key = this.ffzKey.bind(this));
|
2017-11-14 04:12:10 -05:00
|
|
|
|
2017-11-15 14:05:58 -05:00
|
|
|
document.body.addEventListener('keyup', this._ffz_key);
|
|
|
|
}
|
2017-11-14 04:12:10 -05:00
|
|
|
|
|
|
|
node.addEventListener('mousemove',
|
|
|
|
this._ffz_mousemove = this.ffzMouseMove.bind(this));
|
|
|
|
|
|
|
|
node.addEventListener('mouseleave',
|
|
|
|
this._ffz_mouseleave = this.ffzMouseLeave.bind(this));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
cls.prototype.ffzDisableFreeze = function() {
|
|
|
|
this.ffz_freeze_enabled = false;
|
|
|
|
|
|
|
|
if ( this.ffz_frozen )
|
|
|
|
this.ffzUnfreeze();
|
|
|
|
|
|
|
|
if ( this._ffz_outside ) {
|
|
|
|
clearTimeout(this._ffz_outside);
|
|
|
|
this._ffz_outside = null;
|
|
|
|
}
|
|
|
|
|
2018-02-22 18:38:13 -05:00
|
|
|
const node = t.fine.getChildNode(this);
|
2017-11-14 04:12:10 -05:00
|
|
|
if ( ! node )
|
|
|
|
return;
|
|
|
|
|
2017-11-16 15:54:58 -05:00
|
|
|
this._ffz_freeze_visible = false;
|
|
|
|
|
2017-11-14 04:12:10 -05:00
|
|
|
if ( this._ffz_freeze_indicator ) {
|
2017-12-01 15:36:18 -05:00
|
|
|
this._ffz_freeze_indicator.remove();
|
2017-11-14 04:12:10 -05:00
|
|
|
this._ffz_freeze_indicator = null;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( this._ffz_key ) {
|
|
|
|
document.body.removeEventListener('keyup', this._ffz_key);
|
|
|
|
document.body.removeEventListener('keydown', this._ffz_key);
|
|
|
|
this._ffz_key = null;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( this._ffz_mousemove ) {
|
|
|
|
node.removeEventListener('mousemove', this._ffz_mousemove);
|
|
|
|
this._ffz_mousemove = null;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( this._ffz_mouseleave ) {
|
|
|
|
node.removeEventListener('mouseleave', this._ffz_mouseleave);
|
|
|
|
this._ffz_mouseleave = null;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
cls.prototype.ffzKey = function(e) {
|
|
|
|
if (e.altKey === this.ffz_alt &&
|
2017-11-16 15:54:58 -05:00
|
|
|
e.shiftKey === this.ffz_shift &&
|
|
|
|
e.ctrlKey === this.ffz_ctrl &&
|
|
|
|
e.metaKey === this.ffz_meta)
|
|
|
|
return;
|
2017-11-14 04:12:10 -05:00
|
|
|
|
|
|
|
this.ffz_alt = e.altKey;
|
|
|
|
this.ffz_shift = e.shiftKey;
|
|
|
|
this.ffz_ctrl = e.ctrlKey;
|
|
|
|
this.ffz_meta = e.metaKey;
|
|
|
|
|
|
|
|
if ( this.ffz_outside || t.freeze < 2 )
|
|
|
|
return;
|
|
|
|
|
|
|
|
const should_freeze = this.ffzShouldBeFrozen(),
|
|
|
|
changed = should_freeze !== this.ffz_frozen;
|
|
|
|
|
|
|
|
if ( changed )
|
|
|
|
if ( should_freeze )
|
|
|
|
this.ffzFreeze();
|
|
|
|
else
|
|
|
|
this.ffzUnfreeze();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
cls.prototype.ffzMouseMove = function(e) {
|
|
|
|
this.ffz_last_move = Date.now();
|
|
|
|
this.ffz_outside = false;
|
|
|
|
if ( this._ffz_outside ) {
|
|
|
|
clearTimeout(this._ffz_outside);
|
|
|
|
this._ffz_outside = null;
|
|
|
|
}
|
|
|
|
|
|
|
|
// If nothing of interest has happened, stop.
|
|
|
|
if (e.altKey === this.ffz_alt &&
|
2017-11-16 15:54:58 -05:00
|
|
|
e.shiftKey === this.ffz_shift &&
|
|
|
|
e.ctrlKey === this.ffz_ctrl &&
|
|
|
|
e.metaKey === this.ffz_meta &&
|
|
|
|
e.screenY === this.ffz_sy &&
|
|
|
|
e.screenX === this.ffz_sx)
|
|
|
|
return;
|
2017-11-14 04:12:10 -05:00
|
|
|
|
|
|
|
this.ffz_alt = e.altKey;
|
|
|
|
this.ffz_shift = e.shiftKey;
|
|
|
|
this.ffz_ctrl = e.ctrlKey;
|
|
|
|
this.ffz_meta = e.metaKey;
|
|
|
|
this.ffz_sy = e.screenY;
|
|
|
|
this.ffz_sx = e.screenX;
|
|
|
|
|
|
|
|
const should_freeze = this.ffzShouldBeFrozen(),
|
|
|
|
changed = should_freeze !== this.ffz_frozen;
|
|
|
|
|
|
|
|
if ( changed )
|
|
|
|
if ( should_freeze )
|
|
|
|
this.ffzFreeze();
|
|
|
|
else
|
|
|
|
this.ffzUnfreeze();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-11-16 15:54:58 -05:00
|
|
|
cls.prototype.ffzMouseLeave = function() {
|
2017-11-14 04:12:10 -05:00
|
|
|
this.ffz_outside = true;
|
|
|
|
if ( this._ffz_outside )
|
|
|
|
clearTimeout(this._ffz_outside);
|
|
|
|
|
|
|
|
this._ffz_outside = setTimeout(() => this.ffzMaybeUnfreeze(), 64);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-07-03 18:18:39 -04:00
|
|
|
cls.prototype.ffzSetSmoothScroll = function(value) {
|
|
|
|
this.ffz_smooth_scroll = value;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-11-14 04:12:10 -05:00
|
|
|
for(const inst of instances)
|
|
|
|
this.onMount(inst);
|
|
|
|
});
|
|
|
|
|
|
|
|
this.ChatScroller.on('mount', this.onMount, this);
|
|
|
|
this.ChatScroller.on('unmount', this.onUnmount, this);
|
2017-11-16 15:54:58 -05:00
|
|
|
|
|
|
|
this.ChatScroller.on('update', inst => {
|
|
|
|
const should_show = inst.ffz_freeze_enabled && inst.state.ffzFrozen && inst.state.isAutoScrolling,
|
|
|
|
changed = should_show !== inst._ffz_freeze_visible;
|
|
|
|
|
|
|
|
if ( changed )
|
|
|
|
if ( should_show )
|
|
|
|
inst.ffzShowFrozen();
|
|
|
|
else
|
|
|
|
inst.ffzHideFrozen();
|
|
|
|
});
|
|
|
|
|
2017-11-14 04:12:10 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
onMount(inst) {
|
2017-11-16 15:54:58 -05:00
|
|
|
inst.ffzInstallHandler();
|
|
|
|
|
2017-11-14 04:12:10 -05:00
|
|
|
if ( this.freeze !== 0 )
|
|
|
|
inst.ffzEnableFreeze();
|
2018-07-03 18:18:39 -04:00
|
|
|
|
|
|
|
inst.ffzSetSmoothScroll(this.smoothScroll);
|
2017-11-14 04:12:10 -05:00
|
|
|
}
|
|
|
|
|
2017-11-16 15:54:58 -05:00
|
|
|
onUnmount(inst) { // eslint-disable-line class-methods-use-this
|
2017-11-14 04:12:10 -05:00
|
|
|
inst.ffzDisableFreeze();
|
|
|
|
}
|
|
|
|
}
|