2018-12-30 23:41:44 +01:00
import Debug from '../conf/Debug' ;
2018-12-31 03:34:26 +01:00
import PlayerData from './video-data/PlayerData' ;
2019-06-02 23:54:32 +02:00
import ExtensionMode from '../../common/enums/extension-mode.enum' ;
2018-11-14 23:32:37 +01:00
2020-04-13 15:20:29 +02:00
if ( process . env . CHANNEL !== 'stable' ) {
console . log ( "Loading ActionHandler" ) ;
}
2018-11-14 23:32:37 +01:00
class ActionHandler {
2019-09-03 22:55:10 +02:00
constructor ( pageInfo ) {
2019-09-03 23:01:23 +02:00
this . logger = pageInfo . logger ;
2018-11-14 23:32:37 +01:00
this . pageInfo = pageInfo ;
this . settings = pageInfo . settings ;
this . inputs = [ 'input' , 'select' , 'button' , 'textarea' ] ;
2019-06-02 23:54:32 +02:00
this . keyboardLocalDisabled = false ;
2018-11-14 23:32:37 +01:00
}
init ( ) {
2019-07-18 21:25:58 +02:00
this . logger . log ( 'info' , 'debug' , "[ActionHandler::init] starting init" ) ;
2018-11-18 18:44:44 +01:00
2018-11-14 23:32:37 +01:00
this . keyUpActions = [ ] ;
this . keyDownActions = [ ] ;
this . mouseMoveActions = [ ] ;
this . mouseScrollUpActions = [ ] ;
this . mouseScrollDownActions = [ ] ;
this . mouseEnterActions = [ ] ;
this . mouseLeaveActions = [ ] ;
var ths = this ;
var actions ;
try {
if ( this . settings . active . sites [ window . location . host ] . actions ) {
actions = this . settings . active . sites [ window . location . host ] . actions ;
} else {
actions = this . settings . active . actions ;
}
} catch ( e ) {
actions = this . settings . active . actions ;
}
2018-12-31 03:34:26 +01:00
2018-11-14 23:32:37 +01:00
for ( var action of actions ) {
2018-12-31 03:34:26 +01:00
if ( ! action . scopes ) {
2018-11-18 18:44:44 +01:00
continue ;
}
2018-12-31 03:34:26 +01:00
for ( var scope in action . scopes ) {
if ( ! action . scopes [ scope ] . shortcut ) {
continue ;
}
var shortcut = action . scopes [ scope ] . shortcut [ 0 ] ;
if ( shortcut . onKeyDown ) {
this . keyDownActions . push ( {
shortcut : shortcut ,
cmd : action . cmd ,
scope : scope ,
} ) ;
}
if ( shortcut . onKeyUp ) {
this . keyUpActions . push ( {
shortcut : shortcut ,
cmd : action . cmd ,
scope : scope ,
} ) ;
}
if ( shortcut . onScrollUp ) {
this . mouseScrollUpActions . push ( {
shortcut : shortcut ,
cmd : action . cmd ,
scope : scope ,
} ) ;
}
if ( shortcut . onScrollDown ) {
this . mouseScrollDownActions . push ( {
shortcut : shortcut ,
cmd : action . cmd ,
scope : scope ,
} ) ;
}
if ( shortcut . onMouseEnter ) {
this . mouseEnterActions . push ( {
shortcut : shortcut ,
cmd : action . cmd ,
scope : scope ,
} ) ;
}
if ( shortcut . onMouseLeave ) {
this . mouseLeaveActions . push ( {
shortcut : shortcut ,
cmd : action . cmd ,
scope : scope ,
} ) ;
}
if ( shortcut . onMouseMove ) {
this . mouseMoveActions . push ( {
shortcut : shortcut ,
cmd : action . cmd ,
scope : scope ,
} ) ;
}
2018-11-14 23:32:37 +01:00
}
}
document . addEventListener ( 'keydown' , ( event ) => ths . handleKeydown ( event ) ) ;
document . addEventListener ( 'keyup' , ( event ) => ths . handleKeyup ( event ) ) ;
2018-11-18 18:44:44 +01:00
2018-12-02 23:51:34 +01:00
this . pageInfo . setActionHandler ( this ) ;
2019-07-18 21:25:58 +02:00
this . logger . log ( 'info' , 'debug' , "[ActionHandler::init] initialization complete" ) ;
2018-11-14 23:32:37 +01:00
}
2018-12-02 23:51:34 +01:00
registerHandleMouse ( videoData ) {
2020-02-03 22:13:03 +01:00
this . logger . log ( 'info' , [ 'actionHandler' , 'mousemove' ] , "[ActionHandler::registerHandleMouse] registering handle mouse for videodata:" , videoData . id )
2019-07-18 21:25:58 +02:00
2018-12-02 23:51:34 +01:00
var ths = this ;
if ( videoData . player && videoData . player . element ) {
videoData . player . element . addEventListener ( 'mousemove' , ( event ) => ths . handleMouseMove ( event , videoData ) ) ;
}
}
2019-08-25 01:52:04 +02:00
unregisterHandleMouse ( videoData ) {
var ths = this ;
if ( videoData . player && videoData . player . element ) {
videoData . player . element . removeEventListener ( 'mousemove' , ( event ) => ths . handleMouseMove ( event , videoData ) ) ;
}
}
2018-12-02 23:51:34 +01:00
2019-06-02 23:54:32 +02:00
setKeyboardLocal ( state ) {
if ( state === ExtensionMode . Enabled ) {
this . keyboardLocalDisabled = false ;
} else if ( state === ExtensionMode . Disabled ) {
this . keyboardLocalDisabled = true ;
}
// don't do shit on invalid value of state
}
2019-10-27 23:37:13 +01:00
preventAction ( event ) {
2018-11-14 23:32:37 +01:00
var activeElement = document . activeElement ;
2020-01-30 01:06:02 +01:00
if ( this . logger . canLog ( 'keyboard' ) ) {
2019-07-18 21:25:58 +02:00
this . logger . pause ( ) ; // temp disable to avoid recursing;
2020-01-30 01:06:02 +01:00
const preventAction = this . preventAction ( event ) ;
2019-10-27 23:37:13 +01:00
this . logger . resume ( ) ; // undisable
2019-07-18 21:25:58 +02:00
this . logger . log ( 'info' , 'keyboard' , "[ActionHandler::preventAction] Testing whether we're in a textbox or something. Detailed rundown of conditions:\n" +
2018-11-14 23:32:37 +01:00
"is full screen? (yes->allow):" , PlayerData . isFullScreen ( ) ,
2018-11-15 00:18:41 +01:00
"\nis tag one of defined inputs? (yes->prevent):" , this . inputs . indexOf ( activeElement . tagName . toLocaleLowerCase ( ) ) !== - 1 ,
2018-11-14 23:32:37 +01:00
"\nis role = textbox? (yes -> prevent):" , activeElement . getAttribute ( "role" ) === "textbox" ,
"\nis type === 'text'? (yes -> prevent):" , activeElement . getAttribute ( "type" ) === "text" ,
2019-10-27 23:37:13 +01:00
"\nevent.target.isContentEditable? (yes -> prevent):" , event . target . isContentEditable ,
2019-06-02 23:54:32 +02:00
"\nis keyboard local disabled? (yes -> prevent):" , this . keyboardLocalDisabled ,
"\nis keyboard enabled in settings? (no -> prevent)" , this . settings . keyboardShortcutsEnabled ( window . location . hostname ) ,
2019-10-27 23:37:13 +01:00
"\nwill the action be prevented? (yes -> prevent)" , preventAction ,
2018-11-14 23:32:37 +01:00
"\n-----------------{ extra debug info }-------------------" ,
"\ntag name? (lowercase):" , activeElement . tagName , activeElement . tagName . toLocaleLowerCase ( ) ,
"\nrole:" , activeElement . getAttribute ( 'role' ) ,
"\ntype:" , activeElement . getAttribute ( 'type' ) ,
2019-10-27 23:37:13 +01:00
"\ninsta-fail inputs:" , this . inputs ,
"\nevent:" , event ,
"\nevent.target:" , event . target
2018-11-14 23:32:37 +01:00
) ;
}
2018-12-02 23:51:34 +01:00
// lately youtube has allowed you to read and write comments while watching video in
// fullscreen mode. We can no longer do this.
// if (PlayerData.isFullScreen()) {
// return false;
// }
2019-06-02 23:54:32 +02:00
if ( this . keyboardLocalDisabled ) {
return true ;
}
if ( ! this . settings . keyboardShortcutsEnabled ( window . location . hostname ) ) {
return true ;
}
2018-11-14 23:32:37 +01:00
if ( this . inputs . indexOf ( activeElement . tagName . toLocaleLowerCase ( ) ) !== - 1 ) {
return true ;
}
if ( activeElement . getAttribute ( "role" ) === "textbox" ) {
return true ;
}
2019-10-27 23:37:13 +01:00
if ( event . target . isContentEditable ) {
return true ;
}
2018-11-14 23:32:37 +01:00
if ( activeElement . getAttribute ( "type" ) === "text" ) {
return true ;
}
return false ;
}
2019-10-22 01:33:56 +02:00
isLatin ( key ) {
return 'abcdefghijklmnopqrstuvwxyz,.-+1234567890' . indexOf ( key . toLocaleLowerCase ( ) ) !== - 1 ;
}
isActionMatchStandard ( shortcut , event ) {
2018-11-14 23:32:37 +01:00
return shortcut . key === event . key &&
shortcut . ctrlKey === event . ctrlKey &&
shortcut . metaKey === event . metaKey &&
shortcut . altKey === event . altKey &&
shortcut . shiftKey === event . shiftKey
}
2019-10-23 19:34:58 +02:00
isActionMatchKeyCode ( shortcut , event ) {
return shortcut . code === event . code &&
2019-10-22 01:33:56 +02:00
shortcut . ctrlKey === event . ctrlKey &&
shortcut . metaKey === event . metaKey &&
shortcut . altKey === event . altKey &&
shortcut . shiftKey === event . shiftKey
}
isActionMatch ( shortcut , event , isLatin = true ) {
2019-10-23 19:34:58 +02:00
// ASCII and symbols fall back to key code matching, because we don't know for sure that
2019-10-22 01:33:56 +02:00
// regular matching by key is going to work
return isLatin ?
this . isActionMatchStandard ( shortcut , event ) :
2019-10-23 19:34:58 +02:00
this . isActionMatchStandard ( shortcut , event ) || this . isActionMatchKeyCode ( shortcut , event ) ;
2019-10-22 01:33:56 +02:00
}
2018-11-14 23:32:37 +01:00
2018-12-31 03:34:26 +01:00
execAction ( actions , event , videoData ) {
2019-07-18 21:25:58 +02:00
this . logger . log ( 'info' , 'keyboard' , "%c[ActionHandler::execAction] Trying to find and execute action for event. Actions/event: " , "color: #ff0" , actions , event ) ;
2018-11-14 23:32:37 +01:00
2019-11-02 02:20:09 +01:00
const isLatin = event . key ? this . isLatin ( event . key ) : true ;
2019-10-22 01:33:56 +02:00
2018-11-14 23:32:37 +01:00
for ( var action of actions ) {
2019-10-22 01:33:56 +02:00
if ( this . isActionMatch ( action . shortcut , event , isLatin ) ) {
2019-07-18 21:25:58 +02:00
this . logger . log ( 'info' , 'keyboard' , "%c[ActionHandler::execAction] found an action associated with keypress/event: " , "color: #ff0" , action ) ;
2018-11-14 23:32:37 +01:00
for ( var cmd of action . cmd ) {
2018-12-31 03:34:26 +01:00
if ( action . scope === 'page' ) {
if ( cmd . action === "set-ar" ) {
2019-03-10 23:27:50 +01:00
this . pageInfo . setAr ( { type : cmd . arg , ratio : cmd . customArg } ) ;
2019-01-03 02:07:16 +01:00
} else if ( cmd . action === "change-zoom" ) {
2018-12-31 03:34:26 +01:00
this . pageInfo . zoomStep ( cmd . arg ) ;
2019-01-03 02:07:16 +01:00
} else if ( cmd . action === "set-zoom" ) {
this . pageInfo . setZoom ( cmd . arg ) ;
2018-12-31 03:34:26 +01:00
} else if ( cmd . action === "set-stretch" ) {
this . pageInfo . setStretchMode ( cmd . arg ) ;
} else if ( cmd . action === "toggle-pan" ) {
this . pageInfo . setPanMode ( cmd . arg )
} else if ( cmd . action === "pan" ) {
if ( videoData ) {
videoData . panHandler ( event , true ) ;
}
2019-06-02 23:54:32 +02:00
} else if ( cmd . action === 'set-keyboard' ) {
this . setKeyboardLocal ( cmd . arg ) ;
2018-12-31 03:34:26 +01:00
}
2019-06-02 23:54:32 +02:00
} else {
let site = action . scope === 'site' ? window . location . host : '@global' ;
2018-12-31 03:34:26 +01:00
if ( cmd . action === "set-stretch" ) {
2019-06-02 23:54:32 +02:00
this . settings . active . sites [ site ] . stretch = cmd . arg ;
2018-12-31 03:34:26 +01:00
} else if ( cmd . action === "set-alignment" ) {
2019-06-02 23:54:32 +02:00
this . settings . active . sites [ site ] . videoAlignment = cmd . arg ;
2018-12-31 03:34:26 +01:00
} else if ( cmd . action === "set-extension-mode" ) {
2019-06-02 23:54:32 +02:00
this . settings . active . sites [ site ] . status = cmd . arg ;
2018-12-31 03:34:26 +01:00
} else if ( cmd . action === "set-autoar-mode" ) {
2019-06-02 23:54:32 +02:00
this . settings . active . sites [ site ] . arStatus = cmd . arg ;
} else if ( cmd . action === 'set-keyboard' ) {
this . settings . active . sites [ site ] . keyboardShortcutsEnabled = cmd . arg ;
2019-10-28 22:10:15 +01:00
} else if ( cmd . action === 'set-ar-persistence' ) {
this . settings . active . sites [ site ] [ 'cropModePersistence' ] = cmd . arg ;
this . pageInfo . setArPersistence ( cmd . arg ) ;
this . settings . saveWithoutReload ( ) ;
}
if ( cmd . action !== 'set-ar-persistence' ) {
this . settings . save ( ) ;
2018-12-02 23:51:34 +01:00
}
2018-11-14 23:32:37 +01:00
}
}
2019-01-02 20:36:00 +01:00
// če smo našli dejanje za to tipko, potem ne preiskujemo naprej
// if we found an action for this key, we stop searching for a match
2018-11-14 23:32:37 +01:00
return ;
}
}
}
2018-12-02 23:51:34 +01:00
2018-11-14 23:32:37 +01:00
handleKeyup ( event ) {
2019-07-18 21:25:58 +02:00
this . logger . log ( 'info' , 'keyboard' , "%c[ActionHandler::handleKeyup] we pressed a key: " , "color: #ff0" , event . key , " | keyup: " , event . keyup , "event:" , event ) ;
2018-11-14 23:32:37 +01:00
2019-10-27 23:37:13 +01:00
if ( this . preventAction ( event ) ) {
2019-07-18 21:25:58 +02:00
this . logger . log ( 'info' , 'keyboard' , "[ActionHandler::handleKeyup] we are in a text box or something. Doing nothing." ) ;
2018-11-14 23:32:37 +01:00
return ;
}
2018-12-31 03:34:26 +01:00
this . execAction ( this . keyUpActions , event ) ;
2018-11-15 00:18:41 +01:00
}
handleKeydown ( event ) {
2019-09-03 00:48:18 +02:00
this . logger . log ( 'info' , 'keyboard' , "%c[ActionHandler::handleKeydown] we pressed a key: " , "color: #ff0" , event . key , " | keydown: " , event . keydown , "event:" , event )
2018-11-15 00:18:41 +01:00
2019-10-27 23:37:13 +01:00
if ( this . preventAction ( event ) ) {
2019-07-18 21:25:58 +02:00
this . logger . log ( 'info' , 'keyboard' , "[ActionHandler::handleKeydown] we are in a text box or something. Doing nothing." ) ;
2018-11-15 00:18:41 +01:00
return ;
}
2018-11-14 23:32:37 +01:00
2018-12-31 03:34:26 +01:00
this . execAction ( this . keyDownActions , event ) ;
2018-11-14 23:32:37 +01:00
}
2018-12-02 23:51:34 +01:00
handleMouseMove ( event , videoData ) {
2019-07-18 21:25:58 +02:00
this . logger . log ( 'info' , 'keyboard' , "[ActionHandler::handleMouseMove] mouse move is being handled.\nevent:" , event , "\nvideo data:" , videoData ) ;
2018-12-02 23:51:34 +01:00
videoData . panHandler ( event ) ;
2018-12-31 03:34:26 +01:00
this . execAction ( this . mouseMoveActions , event , videoData )
2018-12-02 23:51:34 +01:00
}
2018-12-30 23:41:44 +01:00
}
2020-04-13 15:20:29 +02:00
if ( process . env . CHANNEL !== 'stable' ) {
console . log ( "ActionHandler loaded" ) ;
}
2018-12-30 23:41:44 +01:00
export default ActionHandler ;