if (viewModel) { action(viewModel); } else { this.#attachedViewModels.splice(i, 1); } } } *enumerateLines(searchText) { for (let source of this.#sources) { yield* source.enumerateLines(searchText); } } /** * * @param {Function} createSourceFn (aggregatorApi) used to create Data Source. * aggregatorApi is the way for Data Source to push data * to the Aggregator. */ addSource(createSourceFn) { const api = this.#apiForDataSource(); const source = createSourceFn(api); this.#sources.push(source); } callFunction(dataSource, functionName, ...params) { const source = this.#sources.find( source => source.constructor.name === dataSource ); if (source && source[functionName]) { return source[functionName](params); } return null; } /** * Exposes interface for a datasource to communicate with Aggregator. */ #apiForDataSource() { const aggregator = this; return { refreshSingleLineOnScreen(line) { aggregator.forEachViewModel(vm => vm.refreshSingleLineOnScreen(line)); }, refreshAllLinesOnScreen() { aggregator.forEachViewModel(vm => vm.refreshAllLinesOnScreen()); }, setLayout(layout) { aggregator.forEachViewModel(vm => vm.setLayout(layout)); }, setNotification(notification) { aggregator.forEachViewModel(vm => vm.setNotification(notification)); }, setDisplayMode(displayMode) { aggregator.forEachViewModel(vm => vm.setDisplayMode(displayMode)); }, discardChangesConfirmed() { aggregator.forEachViewModel(vm => vm.discardChangesConfirmed()); }, setPrimaryPasswordAuthenticated(isAuthenticated) { aggregator.forEachViewModel(vm => vm.setPrimaryPasswordAuthenticated(isAuthenticated) ); }, }; } } PK