import { ChangeBuffer } from './ChangeBuffer' ; import { Destroyable } from './Destroyable' ; import { EventBusInterface , EventDispatcher , makeConnectionMessageEvent , MqttMessage } from '../../../events' ; import { TreeNode } from './' ; import { TreeNodeFactory } from './TreeNodeFactory' ; export class Tree < ViewModel extends Destroyable > extends TreeNode < ViewModel > { public connectionId ? : string ; public updateSource ? : EventBusInterface ; public nodeFilter ? : ( node : TreeNode < ViewModel > ) => boolean ; private subscriptionEvent ? : any ; public isTree = true ; private cachedHash = `${ Math . random ( ) }` ; private unmergedMessages : ChangeBuffer = new ChangeBuffer ( ) ; public didUpdate = new EventDispatcher < void > ( ) ; public updateInterval : any ; private paused : boolean = false ; private applyChangesHasCompleted = true ; constructor ( ) { super ( undefined , undefined ) ; } private handleNewData = ( msg ) => { this . unmergedMessages . push ( msg ) ; } ; private runUpdates ( ) { this . updateInterval = setInterval ( ( ) => { if ( ! this . paused && this . applyChangesHasCompleted ) { this . applyChangesHasCompleted = false ; if ( ( window as any ) . requestIdleCallback ) { ; ( window as any ) . requestIdleCallback ( ( ) => this . applyUnmergedChanges ( ) , { timeout : 500 } ) ; } else { this . applyUnmergedChanges ( ) ; } } } , 300 ) ; } public destroy ( ) { super . destroy ( ) ; this . updateInterval && clearInterval ( this . updateInterval ) ; this . updateSource && this . updateSource . unsubscribe ( this . subscriptionEvent , this . handleNewData ) ; this . updateSource = undefined ; this . didUpdate . removeAllListeners ( ) ; } public updateWithConnection ( emitter , connectionId , nodeFilter ? ) { this . updateSource = emitter ; this . connectionId = connectionId ; this . nodeFilter = nodeFilter ; this . subscriptionEvent = makeConnectionMessageEvent ( connectionId ) ; this . updateSource . subscribe ( this . subscriptionEvent , this . handleNewData ) ; this . runUpdates ( ) ; } public hash ( ) { return this . cachedHash ; } public pause ( ) { this . paused = true ; } public resume ( ) { this . paused = false ; } public applyUnmergedChanges ( ) { this . unmergedMessages . popAll ( ) . forEach ( bufferedItem => { const node = TreeNodeFactory . fromMessage < ViewModel > ( bufferedItem . message , bufferedItem . received ) ; if ( ! this . nodeFilter || this . nodeFilter ( node ) ) { this . updateWithNode ( node . firstNode ( ) ) ; } } ) ; this . didUpdate . dispatch ( ) ; this . applyChangesHasCompleted = true ; } public unmergedChanges ( ) { return this . unmergedMessages ; } public stopUpdating ( ) { if ( this . subscriptionEvent && this . updateSource ) { this . updateSource . unsubscribe ( this . subscriptionEvent , this . handleNewData ) ; } } }