import Logger from '../tools/env.logger' ; import Subscription from '../tools/subscription' ; import Subject from '../tools/subject' ; import ServiceElectron from './service.electron' ; import ServiceStreams from './service.streams' ; import { IService } from '../interfaces/interface.service' ; import { app , globalShortcut , powerMonitor } from 'electron' ; import { IPCMessages } from './service.electron' ; const CHotkeyMap = { [ IPCMessages . EHotkeyActionRef . newTab ] : { darwin : [ 'Cmd+T' ] , other : [ 'Ctrl+T' ] } , [ IPCMessages . EHotkeyActionRef . closeTab ] : { darwin : [ 'Cmd+W' ] , other : [ 'Ctrl+w' ] } , [ IPCMessages . EHotkeyActionRef . openLocalFile ] : { darwin : [ 'Cmd+O' ] , other : [ 'Ctrl+O' ] } , [ IPCMessages . EHotkeyActionRef . focusSearchInput ] : { darwin : [ 'Cmd+F' ] , other : [ 'Ctrl+F' ] } , [ IPCMessages . EHotkeyActionRef . selectAllSearchResult ] : { darwin : [ 'Cmd+A' ] , other : [ 'Ctrl+A' ] } , [ IPCMessages . EHotkeyActionRef . openSearchFiltersTab ] : { darwin : [ 'Shift+Cmd+F' ] , other : [ 'Shift+Ctrl+F' ] } , [ IPCMessages . EHotkeyActionRef . selectNextRow ] : { darwin : [ 'Cmd+[' ] , other : [ 'Ctrl+[' ] } , [ IPCMessages . EHotkeyActionRef . selectPrevRow ] : { darwin : [ 'Cmd+]' ] , other : [ 'Ctrl+]' ] } , [ IPCMessages . EHotkeyActionRef . focusMainView ] : { darwin : [ 'Cmd+1' ] , other : [ 'Ctrl+1' ] } , [ IPCMessages . EHotkeyActionRef . focusSearchView ] : { darwin : [ 'Cmd+2' ] , other : [ 'Ctrl+2' ] } , [ IPCMessages . EHotkeyActionRef . sidebarToggle ] : { darwin : [ 'Cmd+B' ] , other : [ 'Ctrl+B' ] } , [ IPCMessages . EHotkeyActionRef . toolbarToggle ] : { darwin : [ 'Cmd+J' ] , other : [ 'Ctrl+J' ] } , [ IPCMessages . EHotkeyActionRef . recentFiles ] : { darwin : [ 'Cmd+P' ] , other : [ 'Ctrl+P' ] } , [ IPCMessages . EHotkeyActionRef . recentFilters ] : { darwin : [ 'Shift+Cmd+P' ] , other : [ 'Shift+Ctrl+P' ] } , [ IPCMessages . EHotkeyActionRef . settings ] : { darwin : [ 'Cmd+,' ] , other : [ 'Ctrl+,' ] } , [ IPCMessages . EHotkeyActionRef . prevTab ] : { darwin : [ 'Shift+Control+Tab' ] , other : [ 'Shift+Ctrl+Tab' ] } , [ IPCMessages . EHotkeyActionRef . nextTab ] : { darwin : [ 'Control+Tab' ] , other : [ 'Ctrl+Tab' ] } , [ IPCMessages . EHotkeyActionRef . showHotkeysMapDialog ] : { other : [ '?' ] } , } ; const CInputRelatedHotkeys = [ 'Cmd+A' , 'Ctrl+A' , 'j' , 'k' , 'J' , 'K' , ',' , '/' , '?' , ] ; export interface IServiceSubjects { openLocalFile : Subject < void > ; } class description class ServiceHotkeys implements IService { private _logger : Logger = new Logger ( 'ServiceHotkeys' ) ; private _subscriptions : { [ key ] : Subscription | undefined ; } = { } ; private _locked : boolean = false ; private _subjects : IServiceSubjects = { openLocalFile : new Subject ( 'openLocalFile' ) , } ; returns public init ( ) { return new Promise ( ( resolve ) => { Promise . all ( [ ServiceElectron . IPC . subscribe ( IPCMessages . HotkeyResume , this . _onHotkeyResume . bind ( this ) ) . then ( ( subscription ) => { this . _subscriptions . onHotkeyResume = subscription ; } ) , ServiceElectron . IPC . subscribe ( IPCMessages . HotkeyPause , this . _onHotkeyPause . bind ( this , false ) ) . then ( ( subscription ) => { this . _subscriptions . onHotkeyPause = subscription ; } ) , ServiceElectron . IPC . subscribe ( IPCMessages . HotkeyInputOut , this . _onHotkeyResume . bind ( this ) ) . then ( ( subscription ) => { this . _subscriptions . onHotkeyInputOut = subscription ; } ) , ServiceElectron . IPC . subscribe ( IPCMessages . HotkeyInputIn , this . _onHotkeyPause . bind ( this , true ) ) . then ( ( subscription ) => { this . _subscriptions . onHotkeyInputIn = subscription ; } ) , ServiceElectron . IPC . subscribe ( IPCMessages . HotkeyLocalCall , this . _onHotkeyLocalCall . bind ( this ) ) . then ( ( subscription ) => { this . _subscriptions . onHotkeyLocalCall = subscription ; } ) , ] ) . then ( ( ) => { powerMonitor . on ( 'resume' , this . _resume . bind ( this , false ) ) ; powerMonitor . on ( 'shutdown' , this . _unbind . bind ( this , false ) ) ; app . on ( 'browser-window-blur' , this . _unbind . bind ( this , false ) ) ; app . on ( 'browser-window-focus' , this . _bind . bind ( this ) ) ; this . _bind ( ) ; resolve ( ) ; } ) ; } ) ; } public destroy ( ) { return new Promise ( ( resolve ) => { Object . keys ( this . _subscriptions ) . forEach ( ( key ) => { ( this . _subscriptions as any ) [ key ] . destroy ( ) ; } ) ; this . _unbind ( ) ; resolve ( ) ; } ) ; } public getName ( ) { return 'ServiceHotkeys' ; } public getSubject ( ) { return this . _subjects ; } private _bind ( ) { this . _locked = false ; Object . keys ( CHotkeyMap ) . forEach ( ( action ) => { const all = ( CHotkeyMap as any ) [ action ] ; const keys = all [ process . platform ] !== undefined ? all [ process . platform ] : all . other ; keys . forEach ( ( shortcut ) => { if ( globalShortcut . isRegistered ( shortcut ) ) { return ; } if ( ! globalShortcut . register ( shortcut , this . _send . bind ( this , action , shortcut ) ) ) { this . _logger . warn ( `Fail to register key "${ shortcut }" for action "${ action }" as shortcut.` ) ; } } ) ; } ) ; } private _unbind ( input = false ) { if ( ! input ) { globalShortcut . unregisterAll ( ) ; this . _locked = true ; } else { CInputRelatedHotkeys . forEach ( ( shortcut ) => { if ( ! globalShortcut . isRegistered ( shortcut ) ) { return ; } globalShortcut . unregister ( shortcut ) ; } ) ; } } private _resume ( ) { const win = ServiceElectron . getBrowserWindow ( ) ; if ( win === undefined ) { return this . _unbind ( false ) ; } if ( ! win . isFocused ) { this . _unbind ( false ) ; } } private _onHotkeyResume ( ) { if ( this . _locked ) { return ; } this . _bind ( ) ; } private _onHotkeyPause ( input = false ) { this . _unbind ( input ) ; } private _onHotkeyLocalCall ( message ) { const msg = message as IPCMessages . HotkeyLocalCall ; if ( this . _locked ) { return ; } this . _send ( msg . action , msg . shortcut ) ; } private _send ( action , shortcut ) { if ( ( this . _subjects as any ) [ action ] !== undefined ) { ( this . _subjects as any ) [ action ] . emit ( ) ; } ServiceElectron . IPC . send ( new IPCMessages . HotkeyCall ( { session : ServiceStreams . getActiveStreamId ( ) , unixtime : Date . now ( ) , action : action , shortcut : shortcut , } ) ) . catch ( ( error ) => { this . _logger . error ( error . message ) ; } ) ; } } export default ( new ServiceHotkeys ( ) ) ;