import { TabsService , IComponentDesc , ITab } from 'chipmunk-client-material' ; import { Subscription , Subject , Observable } from 'rxjs' ; import { IService } from '../interfaces/interface.service' ; import { DefaultViews , CDefaultTabsGuids } from '../states/state.default.toolbar.apps' ; import { Session } from '../controller/session/session' ; import { ControllerToolbarLifecircle } from '../controller/controller.toolbar.lifecircle' ; import { IPC } from '../services/service.electron.ipc' ; import { IPluginData } from './service.plugins' ; import EventsSessionService from './standalone/service.events.session' ; import PluginsService from './service.plugins' ; import ControllerPluginIPC from '../controller/controller.plugin.ipc' ; import TabsSessionsService from './service.sessions.tabs' ; import HotkeysService from './service.hotkeys' ; import LayoutStateService from './standalone/service.layout.state' ; import ElectronIpcService from '../services/service.electron.ipc' ; import * as Toolkit from 'chipmunk.client.toolkit' ; export { CDefaultTabsGuids } ; export interface ISidebarPluginInfo { id : number ; name : string ; displayName : string ; factory : any ; ipc : ControllerPluginIPC ; } export interface IChangeEvent { session : string ; service : TabsService ; } export interface ITabInfo { name : string ; id : string ; } export class ToolbarSessionsService implements IService { private _logger : Toolkit . Logger = new Toolkit . Logger ( 'ToolbarSessionsService' ) ; private _guid : string = Toolkit . guid ( ) ; private _active : string | undefined ; private _subscriptions : { [ key ] : Subscription | Toolkit . Subscription ; } = { } ; private _inputs : { [ key ] : any ; } = { } ; private _sessions : Map < string , TabsService > = new Map ( ) ; private _lifecircle : Map < string , ControllerToolbarLifecircle > = new Map ( ) ; private _subjects : { change : Subject < IChangeEvent | undefined > ; update : Subject < IChangeEvent | undefined > ; } = { change : new Subject < IChangeEvent | undefined > ( ) , update : new Subject < IChangeEvent | undefined > ( ) , } ; constructor ( ) { this . setCommonInputs ( { } ) ; } public init ( ) { return new Promise ( ( resolve ) => { this . _subscriptions . onFocusSearchInput = HotkeysService . getObservable ( ) . focusSearchInput . subscribe ( this . _onFocusSearchInputHotkey . bind ( this ) ) ; this . _subscriptions . onSessionClosed = EventsSessionService . getObservable ( ) . onSessionClosed . subscribe ( this . _onSessionClosed . bind ( this ) ) ; this . _subscriptions . onSessionChange = EventsSessionService . getObservable ( ) . onSessionChange . subscribe ( this . _onSessionChange . bind ( this ) ) ; this . _subscriptions . ViewSwitchEvent = ElectronIpcService . subscribe ( IPC . ViewSwitchEvent , this . _ipc_ViewSwitchEvent . bind ( this ) ) ; TabsSessionsService . setToolbarTabOpener ( this . setActive . bind ( this ) , CDefaultTabsGuids ) ; resolve ( ) ; } ) ; } public getName ( ) { return 'ToolbarSessionsService' ; } public destroy ( ) { Object . keys ( this . _subscriptions ) . forEach ( ( key ) => { this . _subscriptions [ key ] . unsubscribe ( ) ; } ) ; this . _lifecircle . forEach ( ( lifecircle ) => { lifecircle . destroy ( ) ; } ) ; this . _lifecircle . clear ( ) ; } public getObservable ( ) { return { change : this . _subjects . change . asObservable ( ) , update : this . _subjects . update . asObservable ( ) , } ; } public getTabsService ( ) { return this . _active === undefined ? undefined : this . _sessions . get ( this . _active ) ; } public setCommonInputs ( inputs ) { this . _inputs = Object . assign ( { setActiveTab : this . setActive . bind ( this ) , getDefaultsTabGuids : this . getDefaultsGuids . bind ( this ) , } , inputs ) ; } public add ( name , content , guid ? ) { if ( this . _active === undefined ) { return undefined ; } const service = this . _sessions . get ( this . _active ) ; if ( service === undefined ) { return undefined ; } guid = typeof guid !== 'string' ? Toolkit . guid ( ) : guid ; if ( ! service . has ( guid ) ) { content . inputs = this . _injectLifecircleController ( guid , content . inputs === undefined ? { } : content . inputs ) ; service . add ( { guid : guid , name : name , active : true , content : content , } ) ; } this . _sessions . set ( this . _active , service ) ; this . _subjects . update . next ( { session : this . _active , service : service , } ) ; return guid ; } public addByGuid ( guid ) { if ( this . _active === undefined ) { return undefined ; } const tab = this . _getTabByGuid ( guid ) ; const service = this . _sessions . get ( this . _active ) ; if ( service === undefined || tab === undefined ) { return undefined ; } service . add ( tab ) ; this . _sessions . set ( this . _active , service ) ; this . _subjects . update . next ( { session : this . _active , service : service , } ) ; } public remove ( guid ) { if ( this . _active === undefined ) { return undefined ; } const service = this . _sessions . get ( this . _active ) ; if ( service === undefined ) { return undefined ; } const controller = this . _lifecircle . get ( guid ) ; if ( controller !== undefined ) { controller . destroy ( ) ; this . _lifecircle . delete ( guid ) ; } service . remove ( guid ) ; this . _sessions . set ( this . _active , service ) ; this . _subjects . update . next ( { session : this . _active , service : service , } ) ; } public has ( guid ) { if ( this . _active === undefined ) { return false ; } const service = this . _sessions . get ( this . _active ) ; if ( service === undefined ) { return false ; } return service . has ( guid ) ; } public setActive ( guid , session , openTabOnly = false ) { return new Promise ( ( resolve , reject ) => { session = session !== undefined ? session : this . _active ; if ( session === undefined ) { return reject ( new Error ( this . _logger . warn ( `Session guid isn't defined` ) ) ) ; } const service = this . _sessions . get ( session ) ; if ( service === undefined ) { return reject ( new Error ( this . _logger . warn ( `Fail to find tab's service` ) ) ) ; } const tab = service . getActiveTab ( ) ; if ( ! service . has ( guid ) ) { const tab = this . _getTabByGuid ( guid ) ; if ( tab === undefined ) { return reject ( new Error ( this . _logger . warn ( `Fail to find tab "${ guid }". Tab isn't added.` ) ) ) ; } service . add ( tab ) ; } if ( openTabOnly === true ) { if ( tab !== undefined ) { service . setActive ( tab . guid ) ; } } else { service . setActive ( guid ) ; } const controller = this . _lifecircle . get ( guid ) ; if ( controller === undefined ) { return reject ( new Error ( this . _logger . error ( `Attention, ControllerToolbarLifecircle isn't created for "${ guid }"` ) ) ) ; } controller . callOn ( ) . viewready ( resolve ) ; } ) ; } public getDefaultsGuids ( ) { return CDefaultTabsGuids ; } public getInactiveTabs ( session ? ) { session = session === undefined ? this . _active : session ; if ( session === undefined ) { return undefined ; } const service = this . _sessions . get ( session ) ; if ( service === undefined ) { return undefined ; } return this . _getAvailableTabs ( ) . filter ( ( tab ) => { return tab . guid === undefined ? false : ! service . has ( tab . guid ) ; } ) ; } private _onFocusSearchInputHotkey ( ) { if ( this . _active === undefined ) { return ; } const service = this . _sessions . get ( this . _active ) ; if ( service === undefined ) { return ; } LayoutStateService . toolbarMax ( ) ; service . setActive ( CDefaultTabsGuids . search ) ; } private _onSessionClosed ( session ) { const service = this . _sessions . get ( session ) ; if ( service === undefined ) { return ; } service . destroy ( ) ; this . _sessions . delete ( session ) ; if ( this . _active === session ) { this . _active = undefined ; this . _subjects . change . next ( undefined ) ; } } private _onSessionChange ( controller ) { if ( controller === undefined ) { return ; } let service = this . _sessions . get ( controller . getGuid ( ) ) ; if ( service === undefined ) { service = new TabsService ( { guid : `toolbar: ${ controller . getGuid ( ) }` } ) ; this . _getAvailableTabs ( ) . map ( ( tab ) => { if ( tab . guid !== undefined && ! this . _isTabVisibleByDefault ( tab . guid ) ) { return ; } service !== undefined && service . unshift ( tab ) ; } ) ; this . _sessions . set ( controller . getGuid ( ) , service ) ; } this . _active = controller . getGuid ( ) ; this . _subjects . change . next ( { session : this . _active , service : service , } ) ; } private _getAvailableTabs ( ) { const tabs = [ ] ; DefaultViews . forEach ( ( defaultView , i ) => { tabs . push ( { guid : defaultView . guid , name : defaultView . name , active : i === DefaultViews . length - 1 , tabCaptionInjection : defaultView . tabCaptionInjection === undefined ? undefined : { factory : defaultView . tabCaptionInjection , inputs : Object . assign ( defaultView . inputs , this . _inputs ) , resolved : false , } , closable : defaultView . closable , content : { factory : defaultView . factory , inputs : this . _injectLifecircleController ( defaultView . guid , Object . assign ( defaultView . inputs , this . _inputs ) ) , resolved : false , } , } ) ; } ) ; PluginsService . getAvailablePlugins ( ) . forEach ( ( plugin ) => { if ( plugin . factories [ Toolkit . EViewsTypes . sidebarHorizontal ] === undefined ) { return ; } const guid = Toolkit . guid ( ) ; const inputs = Object . assign ( { api : TabsSessionsService . getPluginAPI ( plugin . id ) , session : this . _guid , } , this . _inputs ) ; tabs . push ( { guid : guid , name : plugin . displayName , active : false , content : { factory : plugin . factories [ Toolkit . EViewsTypes . sidebarHorizontal ] , inputs : this . _injectLifecircleController ( guid , inputs ) , resolved : true , } , } ) ; } ) ; return tabs ; } private _injectLifecircleController ( guid , inputs ) { let controller = this . _lifecircle . get ( guid ) ; if ( controller === undefined ) { controller = new ControllerToolbarLifecircle ( guid ) ; this . _lifecircle . set ( guid , controller ) ; } return Object . assign ( { lifecircle : controller , } , inputs ) ; } private _isTabVisibleByDefault ( guid ) { let result = false ; DefaultViews . forEach ( ( defaultView , i ) => { if ( result ) { return ; } if ( defaultView . default === true && defaultView . guid === guid ) { result = true ; } } ) ; return result ; } private _getTabByGuid ( guid ) { if ( typeof guid !== 'string' || guid . trim ( ) === '' ) { return undefined ; } return this . _getAvailableTabs ( ) . find ( ( tab ) => { return tab . guid === guid ; } ) ; } private _ipc_ViewSwitchEvent ( event ) { if ( this . _active === undefined || this . _active !== event . session ) { return ; } LayoutStateService . toolbarMax ( ) ; switch ( event . target ) { case IPC . AvailableViews . SearchResults : this . addByGuid ( CDefaultTabsGuids . search ) ; break ; case IPC . AvailableViews . Charts : this . addByGuid ( CDefaultTabsGuids . charts ) ; break ; case IPC . AvailableViews . TimeMeasurement : this . addByGuid ( CDefaultTabsGuids . timemeasurement ) ; break ; case IPC . AvailableViews . Notifications : this . addByGuid ( CDefaultTabsGuids . notification ) ; break ; } } } export default new ToolbarSessionsService ( ) ;