import { TabsService , IComponentDesc , ITab } from 'chipmunk-client-material' ; import { Subscription , Subject , Observable } from 'rxjs' ; import { IService } from '../interfaces/interface.service' ; import { Session } from '../controller/session/session' ; import { IPluginData } from '../services/service.plugins' ; import { getSharedServices } from './shared.services.sidebar' ; import { DefaultSidebarApps , IDefaultSidebarApp , CGuids , } from '../states/state.default.sidebar.apps' ; import { IPC } from '../services/service.electron.ipc' ; import EventsSessionService from './standalone/service.events.session' ; import TabsSessionsService from './service.sessions.tabs' ; import ControllerPluginIPC from '../controller/controller.plugin.ipc' ; import PluginsService from '../services/service.plugins' ; import ElectronIpcService from '../services/service.electron.ipc' ; import LayoutStateService from '../services/standalone/service.layout.state' ; import * as Toolkit from 'chipmunk.client.toolkit' ; export { ITab } ; export interface ISidebarPluginInfo { id : number ; name : string ; factory : any ; ipc : ControllerPluginIPC ; } export class SidebarSessionsService implements IService { private _logger : Toolkit . Logger = new Toolkit . Logger ( 'SidebarSessionsService' ) ; private _services : Map < string , TabsService > = new Map ( ) ; private _servicesSubs : Map < string , { [ key ] : Subscription ; } > = new Map ( ) ; private _tabs : Map < string , Map < string , ITab > > = new Map ( ) ; private _subscriptions : { [ key ] : Subscription | Toolkit . Subscription ; } = { } ; private _inputs : { [ key ] : any ; } = { } ; private _injected : IComponentDesc | undefined ; private _droppedInjected : string = '' ; private _subjects : { injection : Subject < IComponentDesc | undefined > ; } = { injection : new Subject < IComponentDesc | undefined > ( ) , } ; constructor ( ) { } public init ( ) { return new Promise ( ( resolve ) => { this . _subscriptions . onSessionChange = EventsSessionService . getObservable ( ) . onSessionChange . subscribe ( this . _onSessionChange . bind ( this ) ) ; this . _subscriptions . onSessionClosed = EventsSessionService . getObservable ( ) . onSessionClosed . subscribe ( this . _onSessionClosed . bind ( this ) ) ; this . _subscriptions . onSidebarTitleInjection = EventsSessionService . getObservable ( ) . onSidebarTitleInjection . subscribe ( this . _onSidebarTitleInjection . bind ( this ) ) ; this . _subscriptions . ViewSwitchEvent = ElectronIpcService . subscribe ( IPC . ViewSwitchEvent , this . _ipc_ViewSwitchEvent . bind ( this ) ) ; TabsSessionsService . setSidebarTabOpener ( this . open . bind ( this ) ) ; resolve ( ) ; } ) ; } public getName ( ) { return 'SidebarSessionsService' ; } public destroy ( ) { Object . keys ( this . _subscriptions ) . forEach ( ( key ) => { this . _subscriptions [ key ] . unsubscribe ( ) ; } ) ; this . _services . forEach ( ( serivce ) => { serivce . clear ( ) ; } ) ; this . _services . clear ( ) ; } public getTabsService ( session ) { return this . _services . get ( session ) ; } public setCommonInputs ( inputs ) { this . _inputs = inputs ; } public add ( tabs , session ? ) { const verified_session = this . _verifySessionGuid ( session ) ; if ( verified_session === undefined ) { return ; } tabs = tabs instanceof Array ? tabs : [ tabs ] ; tabs . forEach ( ( tab ) => { this . _add ( tab , verified_session ) ; } ) ; } public addByGuid ( guid , session ? ) { const verified_session = this . _verifySessionGuid ( session ) ; if ( verified_session === undefined ) { return ; } const tabs = this . _getSessionAvailableTabs ( verified_session ) ; if ( tabs instanceof Error ) { return ; } const tab = tabs . get ( guid ) ; if ( tab === undefined ) { this . _logger . warn ( `Fail to find a tab "${ guid }". Tab isn't available in session: ${ verified_session }` ) ; return ; } this . _add ( tab , verified_session , true ) ; } public remove ( tab , session ? ) { const service = this . _getSessionTabsService ( session ) ; if ( service instanceof Error ) { return service ; } service . remove ( tab ) ; return undefined ; } public has ( tab , session ? ) { const verified_session = this . _verifySessionGuid ( session ) ; if ( verified_session === undefined ) { return false ; } const service = this . _services . get ( verified_session ) ; if ( service === undefined ) { return false ; } return service . has ( tab ) ; } public setActive ( tab , session ? ) { const service = this . _getSessionTabsService ( session ) ; if ( service instanceof Error ) { return service ; } service . setActive ( tab ) ; return undefined ; } param guid { string } param session { string } param openTabOnly { bool } public open ( guid , session , openTabOnly = false ) { const service = this . _getSessionTabsService ( session ) ; if ( service instanceof Error ) { return service ; } const active_tab = service . getActiveTab ( ) ; const current = active_tab === undefined ? undefined : active_tab . guid ; if ( ! service . has ( guid ) ) { const available = this . getAvailableTabs ( ) ; if ( available === undefined ) { return new Error ( `No available tabs found` ) ; } available . forEach ( ( tab ) => { if ( service . has ( guid ) ) { return ; } if ( tab . guid === guid ) { this . add ( tab , session ) ; } } ) ; } if ( service . has ( guid ) ) { if ( openTabOnly === false ) { this . setActive ( guid ) ; } else if ( current !== undefined ) { this . setActive ( current ) ; } } return service . has ( guid ) ? undefined : new Error ( `Tab ${ guid } wasn't found in a list of available tabs.` ) ; } public getAvailableTabs ( session ? ) { const verified_session = this . _verifySessionGuid ( session ) ; if ( verified_session === undefined ) { return undefined ; } const tabs = this . _tabs . get ( verified_session ) ; const service = this . _services . get ( verified_session ) ; if ( tabs === undefined || service === undefined ) { return undefined ; } const available = [ ] ; tabs . forEach ( ( tab ) => { if ( tab . guid === undefined || service . has ( tab . guid ) ) { return ; } available . push ( tab ) ; } ) ; return available ; } public getObservable ( ) { return { injection : this . _subjects . injection . asObservable ( ) , } ; } public setTitleInjection ( comp ) { if ( comp === undefined && this . _injected === undefined ) { return ; } if ( comp !== undefined && this . _injected !== undefined && comp . factory !== undefined && this . _injected . factory !== undefined ) { if ( typeof comp . factory . name === 'string' && typeof this . _injected . factory . name === 'string' ) { if ( comp . factory . name === this . _injected . factory . name && Object . keys ( comp . inputs ) . length === Object . keys ( this . _injected . inputs ) . length ) { return ; } } } if ( comp !== undefined && comp . factory !== undefined && typeof comp . factory . name === 'string' ) { const factory = PluginsService . getStoredFactoryByName ( comp . factory . name ) ; if ( factory !== undefined ) { comp . factory = factory ; comp . resolved = true ; } } this . _injected = comp ; this . _subjects . injection . next ( comp ) ; } private _create ( session ) { this . setTitleInjection ( undefined ) ; if ( this . _services . has ( session ) ) { return ; } const tabs = new Map ( ) ; const service = new TabsService ( ) ; const subscriptions = { } ; subscriptions . active = service . getObservable ( ) . active . subscribe ( this . _dropTitleInjectedContent . bind ( this , session ) ) ; this . _services . set ( session , service ) ; this . _servicesSubs . set ( session , subscriptions ) ; DefaultSidebarApps . forEach ( ( description , index ) => { const tab = Object . assign ( { } , description . tab ) ; if ( tab . guid === undefined ) { this . _logger . error ( `Fail to add new tab (${ JSON . stringify ( description . tab ) }) because it doesn't have guid {string}` ) ; return ; } tabs . set ( tab . guid , tab ) ; if ( description . addedAsDefault ) { this . _add ( tab , session , index === 0 ) ; } } ) ; PluginsService . getAvailablePlugins ( ) . forEach ( ( plugin ) => { if ( plugin . factories [ Toolkit . EViewsTypes . sidebarVertical ] === undefined ) { return ; } tabs . set ( plugin . name , { guid : plugin . name , name : plugin . displayName , active : false , content : { factory : plugin . factories [ Toolkit . EViewsTypes . sidebarVertical ] , resolved : true , inputs : { session : session , api : TabsSessionsService . getPluginAPI ( plugin . id ) , sessions : plugin . controllers . sessions , } , } , } ) ; } ) ; this . _tabs . set ( session , tabs ) ; } private _add ( tab , session , active = false ) { if ( typeof tab !== 'object' || tab === null ) { return new Error ( `Tab object isn't defined` ) ; } const service = this . _getSessionTabsService ( session ) ; if ( service instanceof Error ) { return service ; } if ( tab . guid !== undefined && service . has ( tab . guid ) ) { this . setActive ( tab . guid , session ) ; return tab . guid ; } const verified_session = this . _verifySessionGuid ( session ) ; if ( verified_session === undefined ) { return new Error ( `Fail to get session guid` ) ; } if ( tab . guid === undefined ) { tab . guid = Toolkit . guid ( ) ; } if ( tab . content === undefined ) { return new Error ( `Tab doesn't have valid content property` ) ; } tab . content . inputs = this . _addDefaultsInputs ( tab . content . inputs , session , tab . guid ) ; service . add ( tab ) ; this . _services . set ( verified_session , service ) ; if ( active ) { this . setActive ( tab . guid , verified_session ) ; } return tab . guid ; } private _dropTitleInjectedContent ( session , tab ) { const hash = `${ session }-${ tab . guid }` ; if ( hash === this . _droppedInjected ) { return ; } this . setTitleInjection ( undefined ) ; this . _droppedInjected = hash ; } private _getActiveSessionGuid ( ) { const session = TabsSessionsService . getActive ( ) ; return session === undefined ? undefined : session . getGuid ( ) ; } private _verifySessionGuid ( session ? ) { return session === undefined ? this . _getActiveSessionGuid ( ) : session ; } private _getSessionTabsService ( session ? ) { const verified_session = this . _verifySessionGuid ( session ) ; if ( verified_session === undefined ) { return new Error ( `Fail to get session guid` ) ; } const service = this . _services . get ( verified_session ) ; if ( service === undefined ) { return new Error ( this . _logger . warn ( `Fail to get tab's service for session "${ session }"` ) ) ; } return service ; } private _getSessionAvailableTabs ( session ? ) { const verified_session = this . _verifySessionGuid ( session ) ; if ( verified_session === undefined ) { return new Error ( `Fail to get session guid` ) ; } const tabs = this . _tabs . get ( verified_session ) ; if ( tabs === undefined ) { return new Error ( this . _logger . warn ( `Fail to get available tabs for session "${ session }"` ) ) ; } return tabs ; } private _onSessionChange ( controller ) { if ( controller === undefined ) { return ; } this . _create ( controller . getGuid ( ) ) ; } private _onSessionClosed ( session ) { const subscriptions = this . _servicesSubs . get ( session ) ; if ( subscriptions !== undefined ) { Object . keys ( subscriptions ) . forEach ( ( key ) => { subscriptions [ key ] . unsubscribe ( ) ; } ) ; } this . _servicesSubs . delete ( session ) ; const service = this . _services . get ( session ) ; if ( service !== undefined ) { service . destroy ( ) ; } this . _services . delete ( session ) ; this . _tabs . delete ( session ) ; if ( this . _tabs . size === 0 ) { this . setTitleInjection ( undefined ) ; } } private _onSidebarTitleInjection ( component ) { this . setTitleInjection ( component ) ; } private _addDefaultsInputs ( inputs , session , tab ) { inputs = Object . assign ( inputs , this . _inputs ) ; if ( inputs . session === undefined ) { inputs . session = session ; } if ( inputs . close === undefined ) { inputs . close = ( ) => { this . remove ( tab , session ) ; } ; } if ( inputs . services === undefined ) { inputs . services = getSharedServices ( ) ; } return inputs ; } private _ipc_ViewSwitchEvent ( event ) { const active = this . _getActiveSessionGuid ( ) ; if ( active === undefined || active !== event . session ) { return ; } LayoutStateService . sidebarMax ( ) ; switch ( event . target ) { case IPC . AvailableViews . SearchManager : this . open ( CGuids . search , event . session ) ; break ; case IPC . AvailableViews . CommentsManager : this . open ( CGuids . comments , event . session ) ; break ; case IPC . AvailableViews . Shell : this . open ( CGuids . shell , event . session ) ; break ; case IPC . AvailableViews . DLTConnector : this . open ( CGuids . dltdeamon , event . session ) ; break ; case IPC . AvailableViews . Concat : this . open ( CGuids . concat , event . session ) ; break ; case IPC . AvailableViews . Merge : this . open ( CGuids . merging , event . session ) ; break ; } } } export default new SidebarSessionsService ( ) ;