2017-11-14 04:12:10 -05:00
'use strict' ;
// ============================================================================
// Chat Scroller
// ============================================================================
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' ;
2019-06-03 19:47:41 -04:00
const SCROLL _EVENTS = [
'touchmove' ,
'scroll' ,
'wheel' ,
'mousewheel' ,
'DOMMouseScroll'
] ;
2017-11-14 04:12:10 -05:00
2019-06-12 21:13:53 -04:00
let last _id = 0 ;
2017-11-14 04:12:10 -05:00
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' ,
2019-09-07 14:34:40 -04:00
n => n . saveScrollRef && n . handleScrollEvent && ! n . renderLines && n . resume ,
2018-03-14 13:58:04 -04:00
Twilight . CHAT _ROUTES
2017-11-14 04:12:10 -05:00
) ;
this . settings . add ( 'chat.scroller.freeze' , {
default : 0 ,
ui : {
2019-09-12 13:11:08 -04:00
path : 'Chat > Behavior >> Scrolling' ,
2019-06-03 19:47:41 -04:00
title : 'Pause Chat Scrolling' ,
2020-04-22 14:30:34 -04:00
description : 'Automatically stop chat from scrolling when moving the mouse over it or holding a key.\n\n**Note:** Scrolling up in chat will always prevent automatic scrolling, regardless of this setting.' ,
2017-11-14 04:12:10 -05:00
component : 'setting-select-box' ,
data : [
2020-09-10 14:02:39 -04:00
{ value : 0 , title : 'Use Twitch Setting' } ,
2017-11-14 04:12:10 -05:00
{ 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
2019-06-03 19:47:41 -04:00
this . settings . add ( 'chat.scroller.freeze-requires-hover' , {
default : true ,
ui : {
path : 'Chat > Behavior >> Scrolling' ,
title : 'Require the mouse to be over chat to freeze with a hotkey.' ,
component : 'setting-check-box'
}
} ) ;
this . settings . add ( 'chat.scroller.hover-delay' , {
default : 750 ,
ui : {
path : 'Chat > Behavior >> Scrolling' ,
title : 'Hover Timeout' ,
description : 'Chat will only remain frozen due to mouse hovering for this long after the mouse stops moving.' ,
component : 'setting-combo-box' ,
data : [
{ value : 250 , title : '0.25 Seconds' } ,
{ value : 500 , title : '0.50 Seconds' } ,
{ value : 750 , title : '0.75 Seconds' } ,
{ value : 1000 , title : '1 Second' } ,
{ value : 2500 , title : '2.5 Seconds' } ,
{ value : 5000 , title : '5 Seconds' }
]
}
} ) ;
2018-07-03 18:18:39 -04:00
this . settings . add ( 'chat.scroller.smooth-scroll' , {
default : 0 ,
ui : {
2018-07-09 21:35:31 -04:00
path : 'Chat > Behavior >> Scrolling' ,
2018-07-03 18:18:39 -04:00
title : 'Smooth Scrolling' ,
2019-09-12 13:11:08 -04:00
description : '**Note:** This setting has been disabled until such time as someone is able to fix major bugs with it.\n\nSmoothly slide new chat messages into view. Speed will increase as necessary to keep up with chat.' ,
2018-07-03 18:18:39 -04:00
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
}
2019-05-16 14:46:26 -04:00
updateUseKeys ( ) {
const old _use = this . use _keys ;
this . use _keys = false ;
for ( const act of this . chat . context . get ( 'chat.actions.inline' ) )
2019-06-03 19:47:41 -04:00
if ( act && act . display && act . display . keys ) {
2019-05-16 14:46:26 -04:00
this . use _keys = true ;
2019-06-03 19:47:41 -04:00
break ;
}
2019-05-16 14:46:26 -04:00
if ( this . use _keys !== old _use ) {
for ( const inst of this . ChatScroller . instances )
inst && inst . ffzUpdateKeys && inst . ffzUpdateKeys ( ) ;
}
}
2019-06-03 19:47:41 -04:00
async onEnable ( ) {
this . on ( 'i18n:update' , ( ) => this . ChatScroller . forceUpdate ( ) ) ;
this . chat . context . on ( 'changed:chat.actions.inline' , this . updateUseKeys , this ) ;
this . updateUseKeys ( ) ;
this . pause _hover = this . chat . context . get ( 'chat.scroller.freeze-requires-hover' ) ;
this . chat . context . on ( 'changed:chat.scroller.freeze-requires-hover' , val => {
this . pause _hover = val ;
2017-11-14 04:12:10 -05:00
for ( const inst of this . ChatScroller . instances )
2019-06-03 19:47:41 -04:00
inst . ffzMaybeUnpause ( ) ;
} )
2017-11-14 04:12:10 -05:00
2019-06-03 19:47:41 -04:00
this . pause _delay = this . chat . context . get ( 'chat.scroller.hover-delay' ) ;
this . chat . context . on ( 'changed:chat.scroller.hover-delay' , val => {
this . pause _delay = val ;
for ( const inst of this . ChatScroller . instances )
inst . ffzMaybeUnpause ( ) ;
} )
this . pause = this . chat . context . get ( 'chat.scroller.freeze' ) ;
2017-11-14 04:12:10 -05:00
this . chat . context . on ( 'changed:chat.scroller.freeze' , val => {
2019-06-03 19:47:41 -04:00
this . pause = val ;
2017-11-14 04:12:10 -05:00
2019-06-03 19:47:41 -04:00
for ( const inst of this . ChatScroller . instances )
inst . ffzMaybeUnpause ( ) ;
2017-11-14 04:12:10 -05:00
} ) ;
2019-09-12 13:11:08 -04:00
this . smooth _scroll = 0 ; // this.chat.context.get('chat.scroller.smooth-scroll');
2018-07-03 18:18:39 -04:00
this . chat . context . on ( 'changed:chat.scroller.smooth-scroll' , val => {
2019-09-12 13:11:08 -04:00
val = 0 ;
2019-06-03 19:47:41 -04:00
this . smooth _scroll = val ;
2018-07-03 18:18:39 -04:00
2018-07-03 18:39:00 -04:00
for ( const inst of this . ChatScroller . instances )
2018-07-03 18:18:39 -04:00
inst . ffzSetSmoothScroll ( val ) ;
} ) ;
2019-06-03 19:47:41 -04:00
const t = this ,
React = await this . web _munch . findModule ( 'react' ) ,
createElement = React && React . createElement ;
if ( ! createElement )
return t . log . warn ( ` Unable to get React. ` ) ;
2017-11-14 04:12:10 -05:00
this . ChatScroller . ready ( ( cls , instances ) => {
2019-06-03 19:47:41 -04:00
const old _catch = cls . prototype . componentDidCatch ,
2018-03-03 16:38:50 -05:00
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 ,
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-09-25 18:37:14 -04:00
className : 'tw-border-l tw-c-background-alt-2 tw-c-text-base tw-full-width tw-full-height tw-align-items-center tw-flex tw-flex-column tw-justify-content-center tw-relative'
2018-03-03 16:38:50 -05:00
} , [
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
] ) ;
2020-07-14 15:20:09 -04:00
} else {
const out = old _render . call ( this ) ;
try {
const children = out ? . props ? . children ? . props ? . children ,
child = children ? . [ 2 ] ;
2020-09-10 14:02:39 -04:00
if ( child ? . type ? . displayName === 'ChatPausedFooter' )
2020-07-14 15:20:09 -04:00
children [ 2 ] = this . ffzRenderFooter ( ) ;
} catch ( err ) { /* no-op */ }
return out ;
}
2018-03-03 16:38:50 -05:00
}
2017-11-14 04:12:10 -05:00
2019-06-03 19:47:41 -04:00
cls . prototype . ffzInstallHandler = function ( ) {
if ( this . _ffz _installed )
2017-11-14 04:12:10 -05:00
return ;
2019-06-03 19:47:41 -04:00
this . _ffz _installed = true ;
const inst = this ;
2020-09-10 14:02:39 -04:00
inst . ffz _oldScrollEvent = inst . handleScrollEvent ;
inst . ffz _oldScroll = inst . scrollToBottom ;
2019-06-13 22:56:50 -04:00
inst . ffz _outside = true ;
inst . _ffz _accessor = ` _ffz_contains_ ${ last _id ++ } ` ;
2019-06-12 21:13:53 -04:00
t . on ( 'tooltips:mousemove' , this . ffzTooltipHover , this ) ;
t . on ( 'tooltips:leave' , this . ffzTooltipLeave , this ) ;
2019-06-03 19:47:41 -04:00
inst . handleScrollEvent = function ( event ) {
2020-09-10 14:02:39 -04:00
if ( ! inst . scrollRef ? . scrollContent )
2019-06-03 19:47:41 -04:00
return ;
2017-11-14 04:12:10 -05:00
2019-06-03 19:47:41 -04:00
if ( ! ( event . which > 0 || event . type === 'mousewheel' || event . type === 'wheel' || event . type === 'touchmove' ) )
return ;
2018-07-03 18:39:00 -04:00
2019-06-03 19:47:41 -04:00
// How far are we scrolled up?
2020-09-10 14:02:39 -04:00
const scroller = inst . scrollRef . scrollContent ,
offset = scroller . scrollHeight - scroller . scrollTop - scroller . offsetHeight ,
scrolled _up = offset > 10 ;
2018-07-03 18:39:00 -04:00
2020-09-10 14:02:39 -04:00
if ( scrolled _up !== inst . state . ffz _scrolled _up )
inst . setState ( { ffz _scrolled _up : scrolled _up } ) ;
2018-07-03 18:39:00 -04:00
2020-09-10 14:02:39 -04:00
if ( inst . state . isPaused && scrolled _up )
inst . setLoadMoreEnabled ( true ) ;
2018-07-13 14:32:12 -04:00
2020-09-10 14:02:39 -04:00
if ( inst . state . isPaused && ! scrolled _up )
inst . ffzMaybeUnpause ( ) ;
else if ( ! inst . state . isPaused && scrolled _up )
inst . pause ( ) ;
2019-06-03 19:47:41 -04:00
}
2018-07-03 18:18:39 -04:00
2019-06-03 19:47:41 -04:00
const old _resume = inst . resume ;
2018-07-03 18:39:00 -04:00
2019-06-03 19:47:41 -04:00
inst . ffzFastResume = function ( ) {
inst . _ffz _one _fast _scroll = true ;
inst . resume ( ) ;
2018-07-03 18:18:39 -04:00
}
2018-07-03 18:39:00 -04:00
2019-06-03 19:47:41 -04:00
inst . resume = function ( ) {
2020-09-10 14:02:39 -04:00
inst . setState ( { ffz _scrolled _up : false } ) ;
old _resume . call ( this ) ;
2019-06-03 19:47:41 -04:00
}
2018-07-03 18:39:00 -04:00
2019-06-03 19:47:41 -04:00
// Event Registration
2018-07-03 18:39:00 -04:00
2019-06-03 19:47:41 -04:00
const Mousetrap = t . web _munch . getModule ( 'mousetrap' ) || window . Mousetrap ;
if ( Mousetrap != null ) {
Mousetrap . unbind ( 'alt' , 'keydown' ) ;
Mousetrap . unbind ( 'alt' , 'keyup' ) ;
}
2018-07-03 18:39:00 -04:00
2019-06-03 19:47:41 -04:00
inst . ffzHandleKey = inst . ffzHandleKey . bind ( inst ) ;
2019-06-08 17:35:48 -04:00
window . addEventListener ( 'keydown' , inst . ffzHandleKey ) ;
window . addEventListener ( 'keyup' , inst . ffzHandleKey ) ;
2017-11-16 15:54:58 -05:00
2019-06-03 19:47:41 -04:00
inst . hoverPause = inst . ffzMouseMove . bind ( inst ) ;
inst . hoverResume = inst . ffzMouseLeave . bind ( inst ) ;
2017-11-16 15:54:58 -05:00
2019-06-03 19:47:41 -04:00
const node = t . fine . getChildNode ( inst ) ;
if ( node )
node . addEventListener ( 'mousemove' , inst . hoverPause ) ;
2019-04-30 15:18:29 -04:00
2020-09-10 14:02:39 -04:00
const scroller = this . scrollRef ? . scrollContent ;
2019-06-03 19:47:41 -04:00
if ( scroller ) {
for ( const event of SCROLL _EVENTS ) {
scroller . removeEventListener ( event , inst . ffz _oldScrollEvent ) ;
scroller . addEventListener ( event , inst . handleScrollEvent ) ;
2018-07-03 18:18:39 -04:00
}
2018-01-15 20:40:54 -05:00
}
2019-06-03 19:47:41 -04:00
// We need to refresh the element to make sure it's using the correct
// event handlers for mouse enter / leave.
inst . forceUpdate ( ) ;
2019-10-13 00:41:09 -04:00
t . emit ( 'site:dom-update' , 'chat-scroller' , inst ) ;
2019-06-03 19:47:41 -04:00
}
2019-04-30 15:18:29 -04:00
2019-06-03 19:47:41 -04:00
cls . prototype . ffzSetSmoothScroll = function ( value ) {
this . ffz _smooth _scroll = value ;
this . ffzMaybeUnpause ( ) ;
}
2017-11-16 15:54:58 -05:00
2019-06-03 19:47:41 -04:00
// Event Handling
2017-11-22 15:39:38 -05:00
2019-06-03 19:47:41 -04:00
cls . prototype . ffzReadKeysFromEvent = function ( event ) {
if ( event . altKey === this . ffz _alt &&
event . shiftKey === this . ffz _shift &&
event . ctrlKey === this . ffz _ctrl &&
event . metaKey === this . ffz _meta )
return false ;
2017-11-16 15:54:58 -05:00
2019-06-03 19:47:41 -04:00
this . ffz _alt = event . altKey ;
this . ffz _shift = event . shiftKey ;
this . ffz _ctrl = event . ctrlKey ;
this . ffz _meta = event . metaKey ;
return true ;
2017-11-14 04:12:10 -05:00
}
2019-06-03 19:47:41 -04:00
cls . prototype . ffzHandleKey = function ( event ) {
if ( ! this . ffzReadKeysFromEvent ( event ) )
2017-11-14 04:12:10 -05:00
return ;
2019-06-03 19:47:41 -04:00
this . ffzUpdateKeyTags ( ) ;
2017-11-14 04:12:10 -05:00
2020-09-10 14:02:39 -04:00
if ( ( t . pause _hover && this . ffz _outside ) || this . ffzGetMode ( ) < 2 )
2019-06-03 19:47:41 -04:00
return ;
2017-11-14 04:12:10 -05:00
2019-06-03 19:47:41 -04:00
const should _pause = this . ffzShouldBePaused ( ) ,
changed = should _pause !== this . state . isPaused ;
2017-11-14 04:12:10 -05:00
2019-06-03 19:47:41 -04:00
if ( changed )
if ( should _pause ) {
this . pause ( ) ;
2020-09-10 14:02:39 -04:00
if ( ! this . state . ffz _scrolled _up )
this . setLoadMoreEnabled ( false ) ;
2019-06-03 19:47:41 -04:00
} else
this . resume ( ) ;
2017-11-14 04:12:10 -05:00
}
2019-06-03 19:47:41 -04:00
cls . prototype . ffzInstallHoverTimer = function ( ) {
if ( this . _ffz _hover _timer )
return ;
2017-11-14 04:12:10 -05:00
2019-06-03 19:47:41 -04:00
this . _ffz _hover _timer = setInterval ( ( ) => {
if ( this . state . isPaused && this . ffzShouldBePaused ( ) )
return ;
2017-11-14 04:12:10 -05:00
2019-06-03 19:47:41 -04:00
this . ffzMaybeUnpause ( ) ;
} , 50 ) ;
}
2017-11-14 04:12:10 -05:00
2019-06-03 19:47:41 -04:00
cls . prototype . ffzMouseMove = function ( event ) {
this . ffz _last _move = Date . now ( ) ;
const was _outside = this . ffz _outside ;
this . ffz _outside = false ;
2017-11-16 15:54:58 -05:00
2019-06-03 19:47:41 -04:00
if ( this . _ffz _outside _timer ) {
clearTimeout ( this . _ffz _outside _timer ) ;
this . _ffz _outside _timer = null ;
2017-11-14 04:12:10 -05:00
}
2019-06-03 19:47:41 -04:00
const keys _updated = this . ffzReadKeysFromEvent ( event ) ;
2017-11-14 04:12:10 -05:00
2019-06-03 19:47:41 -04:00
// If nothing changed, stop processing.
if ( ! keys _updated && event . screenX === this . ffz _sx && event . screenY === this . ffz _sy ) {
if ( was _outside )
this . ffzUpdateKeyTags ( ) ;
2017-11-14 04:12:10 -05:00
2019-06-03 19:47:41 -04:00
return ;
2017-11-14 04:12:10 -05:00
}
2019-06-03 19:47:41 -04:00
this . ffz _sx = event . screenX ;
this . ffz _sy = event . screenY ;
2017-11-14 04:12:10 -05:00
2019-06-03 19:47:41 -04:00
if ( keys _updated || was _outside )
this . ffzUpdateKeyTags ( ) ;
2017-11-14 04:12:10 -05:00
2019-06-03 19:47:41 -04:00
const should _pause = this . ffzShouldBePaused ( ) ,
changed = should _pause !== this . state . isPaused ;
2017-11-14 04:12:10 -05:00
2019-06-03 19:47:41 -04:00
if ( changed )
if ( should _pause ) {
this . pause ( ) ;
this . ffzInstallHoverTimer ( ) ;
2020-09-10 14:02:39 -04:00
if ( ! this . state . ffz _scrolled _up )
this . setLoadMoreEnabled ( false ) ;
2019-05-16 14:46:26 -04:00
2019-06-03 19:47:41 -04:00
} else
this . resume ( ) ;
}
2017-11-14 04:12:10 -05:00
2019-06-03 19:47:41 -04:00
cls . prototype . ffzMouseLeave = function ( ) {
this . ffz _outside = true ;
if ( this . _ffz _outside _timer )
clearTimeout ( this . _ffz _outside _timer ) ;
2017-11-14 04:12:10 -05:00
2019-06-03 19:47:41 -04:00
this . _ffz _outside _timer = setTimeout ( ( ) => this . ffzMaybeUnpause ( ) , 64 ) ;
this . ffzUpdateKeyTags ( ) ;
2017-11-14 04:12:10 -05:00
}
2019-06-12 21:13:53 -04:00
cls . prototype . ffzTooltipHover = function ( target , tip , event ) {
if ( target [ this . _ffz _accessor ] == null ) {
2020-09-10 14:02:39 -04:00
const scroller = this . scrollRef ? . scrollContent ;
2019-06-12 21:13:53 -04:00
target [ this . _ffz _accessor ] = scroller ? scroller . contains ( target ) : false ;
}
if ( target [ this . _ffz _accessor ] )
this . ffzMouseMove ( event ) ;
}
cls . prototype . ffzTooltipLeave = function ( target ) {
if ( this . ffz _outside )
return ;
if ( target [ this . _ffz _accessor ] == null ) {
2020-09-10 14:02:39 -04:00
const scroller = this . scrollRef ? . scrollContent ;
2019-06-12 21:13:53 -04:00
target [ this . _ffz _accessor ] = scroller ? scroller . contains ( target ) : false ;
}
if ( target [ this . _ffz _accessor ] )
this . ffzMouseLeave ( ) ;
}
2017-11-14 04:12:10 -05:00
2019-06-03 19:47:41 -04:00
// Keyboard Stuff
cls . prototype . ffzUpdateKeyTags = function ( ) {
if ( ! this . _ffz _key _frame )
this . _ffz _key _frame = requestAnimationFrame ( ( ) => this . ffz _updateKeyTags ( ) ) ;
2019-05-16 14:46:26 -04:00
}
2019-06-03 19:47:41 -04:00
cls . prototype . ffz _updateKeyTags = function ( ) {
this . _ffz _key _frame = null ;
2019-05-16 14:46:26 -04:00
if ( ! t . use _keys && this . ffz _use _keys === t . use _keys )
return ;
2020-09-10 14:02:39 -04:00
if ( ! this . scrollRef ? . root )
2019-05-16 14:46:26 -04:00
return ;
this . ffz _use _keys = t . use _keys ;
2020-09-10 14:02:39 -04:00
this . scrollRef . root . classList . toggle ( 'ffz--keys' , t . use _keys ) ;
2019-05-16 14:46:26 -04:00
2020-09-10 14:02:39 -04:00
const ds = this . scrollRef . root . dataset ;
2019-05-16 14:46:26 -04:00
if ( ! t . use _keys ) {
delete ds . alt ;
delete ds . ctrl ;
delete ds . shift ;
delete ds . meta ;
} else {
ds . alt = ! this . ffz _outside && this . ffz _alt ;
ds . ctrl = ! this . ffz _outside && this . ffz _ctrl ;
ds . shift = ! this . ffz _outside && this . ffz _shift ;
ds . meta = ! this . ffz _outside && this . ffz _meta ;
}
}
2017-11-14 04:12:10 -05:00
2019-06-03 19:47:41 -04:00
// Pause Stuff
2019-05-16 14:46:26 -04:00
2019-06-03 19:47:41 -04:00
cls . prototype . ffzShouldBePaused = function ( since ) {
if ( since == null )
since = Date . now ( ) - this . ffz _last _move ;
2019-05-16 14:46:26 -04:00
2020-09-10 14:02:39 -04:00
if ( this . state . ffz _scrolled _up )
return true ;
const mode = this . ffzGetMode ( ) ,
2019-06-03 19:47:41 -04:00
require _hover = t . pause _hover ;
2020-09-10 14:02:39 -04:00
return ( ! require _hover || ! this . ffz _outside ) && (
2019-06-03 19:47:41 -04:00
( this . ffz _ctrl && ( mode === 2 || mode === 6 ) ) ||
( this . ffz _meta && ( mode === 3 || mode === 7 ) ) ||
( this . ffz _alt && ( mode === 4 || mode === 8 ) ) ||
( this . ffz _shift && ( mode === 5 || mode === 9 ) ) ||
( ! this . ffz _outside && since < t . pause _delay && ( mode === 1 || mode > 5 ) )
) ;
2020-09-10 14:02:39 -04:00
}
2017-11-14 04:12:10 -05:00
2020-09-10 14:02:39 -04:00
cls . prototype . ffzGetMode = function ( ) {
let mode = t . pause ;
if ( mode === 0 && ! this . props . mouseoverPausingDisabled ) {
const setting = this . props . pauseSetting ;
if ( setting === 'MOUSEOVER_ALTKEY' )
mode = 8 ;
else if ( setting === 'MOUSEOVER' )
mode = 1 ;
else if ( setting === 'ALTKEY' )
mode = 4 ;
}
return mode ;
2019-06-03 19:47:41 -04:00
}
2017-11-14 04:12:10 -05:00
2019-06-03 19:47:41 -04:00
cls . prototype . ffzMaybeUnpause = function ( ) {
if ( this . state . isPaused && ! this . _ffz _unpause _frame )
this . _ffz _unpause _frame = requestAnimationFrame ( ( ) => {
this . _ffz _unpause _frame = null ;
if ( this . state . isPaused && ! this . ffzShouldBePaused ( ) )
this . resume ( ) ;
} ) ;
}
2019-05-16 14:46:26 -04:00
2020-07-14 15:20:09 -04:00
cls . prototype . ffzRenderFooter = function ( ) {
2019-06-12 21:13:53 -04:00
let msg , cls = '' ;
2020-09-10 14:02:39 -04:00
if ( this . state . ffz _scrolled _up )
msg = t . i18n . t ( 'chat.messages-below' , 'Chat Paused Due to Scroll' ) ;
else if ( this . state . isPaused ) {
const f = this . ffzGetMode ( ) ,
2019-06-03 19:47:41 -04:00
reason = f === 2 ? t . i18n . t ( 'key.ctrl' , 'Ctrl Key' ) :
f === 3 ? t . i18n . t ( 'key.meta' , 'Meta Key' ) :
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' ) ;
2020-04-03 19:30:28 -04:00
msg = t . i18n . t ( 'chat.paused' , 'Chat Paused Due to {reason}' , { reason } ) ;
2019-06-12 21:13:53 -04:00
cls = 'ffz--freeze-indicator' ;
2019-06-03 19:47:41 -04:00
2020-09-10 14:02:39 -04:00
} else
2020-07-14 15:20:09 -04:00
return createElement ( 'div' , {
className : ` chat-scroll-footer__placeholder tw-flex tw-justify-content-center tw-relative ${ cls } `
} , null ) ;
2017-11-14 04:12:10 -05:00
2019-06-03 19:47:41 -04:00
return createElement ( 'div' , {
2020-07-14 15:20:09 -04:00
className : ` chat-scroll-footer__placeholder tw-flex tw-justify-content-center tw-relative ${ cls } `
} , createElement ( 'div' , {
className : 'tw-absolute tw-border-radius-medium tw-bottom-0 tw-c-background-overlay tw-c-text-overlay tw-mg-b-1'
} , createElement ( 'button' , {
className : 'tw-align-items-center tw-align-middle tw-border-bottom-left-radius-medium tw-border-bottom-right-radius-medium tw-border-top-left-radius-medium tw-border-top-right-radius-medium tw-core-button tw-core-button--overlay tw-core-button--text tw-inline-flex tw-interactive tw-justify-content-center tw-overflow-hidden tw-relative' ,
'data-a-target' : 'chat-list-footer' ,
onClick : this . ffzFastResume
} , createElement ( 'div' , {
className : 'tw-align-items-center tw-core-button-label tw-flex tw-flex-grow-0'
} , createElement ( 'div' , {
className : 'tw-flex-grow-0'
} , msg ) ) ) ) ) ;
2018-07-03 18:18:39 -04:00
}
2019-06-03 19:47:41 -04:00
// Do the thing~
2018-07-03 18:18:39 -04:00
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 ) ;
}
onMount ( inst ) {
2019-06-03 19:47:41 -04:00
inst . ffzSetSmoothScroll ( this . smooth _scroll ) ;
2017-11-16 15:54:58 -05:00
inst . ffzInstallHandler ( ) ;
2017-11-14 04:12:10 -05:00
}
2019-06-08 17:35:48 -04:00
onUnmount ( inst ) { // eslint-disable-line class-methods-use-this
2019-06-12 21:13:53 -04:00
this . off ( 'tooltips:mousemove' , inst . ffzTooltipHover , inst ) ;
this . off ( 'tooltips:leave' , inst . ffzTooltipLeave , inst ) ;
2019-06-08 17:35:48 -04:00
window . removeEventListener ( 'keydown' , inst . ffzHandleKey ) ;
window . removeEventListener ( 'keyup' , inst . ffzHandleKey ) ;
2017-11-14 04:12:10 -05:00
}
}