import { OnDestroy } from "@angular/core"; import { select, Store } from "@ngrx/store"; import { IMessagingActionTmpl, IWindowMessaging } from "./messaging/types"; import { ngViewerActionAddNgLayer, ngViewerActionRemoveNgLayer } from "./services/state/ngViewerState/actions"; import { viewerStateSelectAtlas } from "./services/state/viewerState/actions"; import { viewerStateFetchedAtlasesSelector } from "./services/state/viewerState/selectors"; import { generalActionError } from "./services/stateStore.helper"; export class MessagingGlue implements IWindowMessaging, OnDestroy { private onDestroyCb: (() => void)[] = [] private tmplSpIdToAtlasId = new Map<string, string>() private mapIdUnload = new Map<string, () => void>() ngOnDestroy(){ while(this.onDestroyCb.length > 0) this.onDestroyCb.pop()() } constructor(private store: Store<any>){ const sub = this.store.pipe( select(viewerStateFetchedAtlasesSelector) ).subscribe((atlases: any[]) => { for (const atlas of atlases) { const { ['@id']: atlasId, templateSpaces } = atlas for (const tmpl of templateSpaces) { const { ['@id']: tmplId } = tmpl this.tmplSpIdToAtlasId.set(tmplId, atlasId) } } }) this.onDestroyCb.push(() => sub.unsubscribe()) } /** * it is important to not use select temlate by id. always go from the highest hierarchy, * and enforce single direction flow when possible */ loadTempladById( payload: IMessagingActionTmpl['loadTemplate'] ){ const atlasId = this.tmplSpIdToAtlasId.get(payload['@id']) if (!atlasId) { return this.store.dispatch( generalActionError({ message: `atlas id with the corresponding templateId ${payload['@id']} not found.` }) ) } this.store.dispatch( viewerStateSelectAtlas({ atlas: { ['@id']: atlasId, template: { ['@id']: payload['@id'] } } }) ) } loadResource(payload: IMessagingActionTmpl['loadResource']){ const { unload, url, ["@type"]: type, ["@id"]: swcLayerUuid, resourceParam } = payload if (type === 'swc') { const { transform } = resourceParam const layer = { name: swcLayerUuid, id: swcLayerUuid, source: `swc://${url}`, mixability: 'mixable', type: "segmentation", "segments": [ "1" ], transform, } this.store.dispatch( ngViewerActionAddNgLayer({ layer }) ) this.mapIdUnload.set(swcLayerUuid, () => { this.store.dispatch( ngViewerActionRemoveNgLayer({ layer: { name: swcLayerUuid } }) ) unload() }) } } unloadResource(payload: IMessagingActionTmpl['unloadResource']) { const { ["@id"]: id } = payload const cb = this.mapIdUnload.get(id) if (!cb) { throw new Error(`Unload resource id ${id} does not exist.`) } cb() this.mapIdUnload.delete(id) } }