1 |
|
2 |
|
3 | import { Dialog, showDialog } from '@jupyterlab/apputils';
|
4 | import { CodeCell, createCellSearchProvider } from '@jupyterlab/cells';
|
5 | import { SearchProvider } from '@jupyterlab/documentsearch';
|
6 | import { nullTranslator } from '@jupyterlab/translation';
|
7 | import { ArrayExt } from '@lumino/algorithm';
|
8 | import { NotebookPanel } from './panel';
|
9 |
|
10 |
|
11 |
|
12 | export class NotebookSearchProvider extends SearchProvider {
|
13 | |
14 |
|
15 |
|
16 |
|
17 |
|
18 |
|
19 | constructor(widget, translator = nullTranslator) {
|
20 | super(widget);
|
21 | this.translator = translator;
|
22 | this._textSelection = null;
|
23 | this._currentProviderIndex = null;
|
24 | this._delayedActiveCellChangeHandler = null;
|
25 | this._onSelection = false;
|
26 | this._selectedCells = 1;
|
27 | this._selectedLines = 0;
|
28 | this._query = null;
|
29 | this._searchProviders = [];
|
30 | this._editorSelectionsObservable = null;
|
31 | this._selectionSearchMode = 'cells';
|
32 | this._selectionLock = false;
|
33 | this._searchActive = false;
|
34 | this._handleHighlightsAfterActiveCellChange =
|
35 | this._handleHighlightsAfterActiveCellChange.bind(this);
|
36 | this.widget.model.cells.changed.connect(this._onCellsChanged, this);
|
37 | this.widget.content.activeCellChanged.connect(this._onActiveCellChanged, this);
|
38 | this.widget.content.selectionChanged.connect(this._onCellSelectionChanged, this);
|
39 | this.widget.content.stateChanged.connect(this._onNotebookStateChanged, this);
|
40 | this._observeActiveCell();
|
41 | this._filtersChanged.connect(this._setEnginesSelectionSearchMode, this);
|
42 | }
|
43 | _onNotebookStateChanged(_, args) {
|
44 | if (args.name === 'mode') {
|
45 |
|
46 | window.setTimeout(() => {
|
47 | var _a;
|
48 | if (args.newValue === 'command' &&
|
49 | ((_a = document.activeElement) === null || _a === void 0 ? void 0 : _a.closest('.jp-DocumentSearch-overlay'))) {
|
50 |
|
51 | return;
|
52 | }
|
53 | this._updateSelectionMode();
|
54 | this._filtersChanged.emit();
|
55 | }, 0);
|
56 | }
|
57 | }
|
58 | |
59 |
|
60 |
|
61 |
|
62 |
|
63 |
|
64 | static isApplicable(domain) {
|
65 |
|
66 |
|
67 | return domain instanceof NotebookPanel;
|
68 | }
|
69 | |
70 |
|
71 |
|
72 |
|
73 |
|
74 |
|
75 |
|
76 |
|
77 |
|
78 |
|
79 |
|
80 |
|
81 | static createNew(widget, translator) {
|
82 | return new NotebookSearchProvider(widget, translator);
|
83 | }
|
84 | |
85 |
|
86 |
|
87 | get currentMatchIndex() {
|
88 | let agg = 0;
|
89 | let found = false;
|
90 | for (let idx = 0; idx < this._searchProviders.length; idx++) {
|
91 | const provider = this._searchProviders[idx];
|
92 | if (this._currentProviderIndex == idx) {
|
93 | const localMatch = provider.currentMatchIndex;
|
94 | if (localMatch === null) {
|
95 | return null;
|
96 | }
|
97 | agg += localMatch;
|
98 | found = true;
|
99 | break;
|
100 | }
|
101 | else {
|
102 | agg += provider.matchesCount;
|
103 | }
|
104 | }
|
105 | return found ? agg : null;
|
106 | }
|
107 | |
108 |
|
109 |
|
110 | get matchesCount() {
|
111 | return this._searchProviders.reduce((sum, provider) => (sum += provider.matchesCount), 0);
|
112 | }
|
113 | |
114 |
|
115 |
|
116 |
|
117 |
|
118 | get isReadOnly() {
|
119 | var _a, _b, _c;
|
120 | return (_c = (_b = (_a = this.widget) === null || _a === void 0 ? void 0 : _a.content.model) === null || _b === void 0 ? void 0 : _b.readOnly) !== null && _c !== void 0 ? _c : false;
|
121 | }
|
122 | |
123 |
|
124 |
|
125 | get replaceOptionsSupport() {
|
126 | return {
|
127 | preserveCase: true
|
128 | };
|
129 | }
|
130 | getSelectionState() {
|
131 | const cellMode = this._selectionSearchMode === 'cells';
|
132 | const selectedCount = cellMode ? this._selectedCells : this._selectedLines;
|
133 | return selectedCount > 1
|
134 | ? 'multiple'
|
135 | : selectedCount === 1 && !cellMode
|
136 | ? 'single'
|
137 | : 'none';
|
138 | }
|
139 | |
140 |
|
141 |
|
142 |
|
143 |
|
144 |
|
145 |
|
146 |
|
147 |
|
148 |
|
149 |
|
150 | dispose() {
|
151 | var _a;
|
152 | if (this.isDisposed) {
|
153 | return;
|
154 | }
|
155 | this.widget.content.activeCellChanged.disconnect(this._onActiveCellChanged, this);
|
156 | (_a = this.widget.model) === null || _a === void 0 ? void 0 : _a.cells.changed.disconnect(this._onCellsChanged, this);
|
157 | this.widget.content.stateChanged.disconnect(this._onNotebookStateChanged, this);
|
158 | this.widget.content.selectionChanged.disconnect(this._onCellSelectionChanged, this);
|
159 | this._stopObservingLastCell();
|
160 | super.dispose();
|
161 | const index = this.widget.content.activeCellIndex;
|
162 | this.endQuery()
|
163 | .then(() => {
|
164 | if (!this.widget.isDisposed) {
|
165 | this.widget.content.activeCellIndex = index;
|
166 | }
|
167 | })
|
168 | .catch(reason => {
|
169 | console.error(`Fail to end search query in notebook:\n${reason}`);
|
170 | });
|
171 | }
|
172 | |
173 |
|
174 |
|
175 |
|
176 |
|
177 | getFilters() {
|
178 | const trans = this.translator.load('jupyterlab');
|
179 | return {
|
180 | output: {
|
181 | title: trans.__('Search Cell Outputs'),
|
182 | description: trans.__('Search in the cell outputs.'),
|
183 | default: false,
|
184 | supportReplace: false
|
185 | },
|
186 | selection: {
|
187 | title: this._selectionSearchMode === 'cells'
|
188 | ? trans._n('Search in %1 Selected Cell', 'Search in %1 Selected Cells', this._selectedCells)
|
189 | : trans._n('Search in %1 Selected Line', 'Search in %1 Selected Lines', this._selectedLines),
|
190 | description: trans.__('Search only in the selected cells or text (depending on edit/command mode).'),
|
191 | default: false,
|
192 | supportReplace: true
|
193 | }
|
194 | };
|
195 | }
|
196 | |
197 |
|
198 |
|
199 |
|
200 |
|
201 |
|
202 | _updateSelectionMode() {
|
203 | if (this._selectionLock) {
|
204 | return;
|
205 | }
|
206 | this._selectionSearchMode =
|
207 | this._selectedCells === 1 &&
|
208 | this.widget.content.mode === 'edit' &&
|
209 | this._selectedLines !== 0
|
210 | ? 'text'
|
211 | : 'cells';
|
212 | }
|
213 | |
214 |
|
215 |
|
216 |
|
217 |
|
218 |
|
219 | getInitialQuery() {
|
220 | var _a;
|
221 |
|
222 | return ((_a = window.getSelection()) === null || _a === void 0 ? void 0 : _a.toString()) || '';
|
223 | }
|
224 | |
225 |
|
226 |
|
227 | async clearHighlight() {
|
228 | this._selectionLock = true;
|
229 | if (this._currentProviderIndex !== null &&
|
230 | this._currentProviderIndex < this._searchProviders.length) {
|
231 | await this._searchProviders[this._currentProviderIndex].clearHighlight();
|
232 | this._currentProviderIndex = null;
|
233 | }
|
234 | this._selectionLock = false;
|
235 | }
|
236 | |
237 |
|
238 |
|
239 |
|
240 |
|
241 |
|
242 |
|
243 | async highlightNext(loop = true, options) {
|
244 | const match = await this._stepNext(false, loop, options);
|
245 | return match !== null && match !== void 0 ? match : undefined;
|
246 | }
|
247 | |
248 |
|
249 |
|
250 |
|
251 |
|
252 |
|
253 |
|
254 | async highlightPrevious(loop = true, options) {
|
255 | const match = await this._stepNext(true, loop, options);
|
256 | return match !== null && match !== void 0 ? match : undefined;
|
257 | }
|
258 | |
259 |
|
260 |
|
261 |
|
262 |
|
263 |
|
264 |
|
265 | async startQuery(query, filters) {
|
266 | if (!this.widget) {
|
267 | return;
|
268 | }
|
269 | await this.endQuery();
|
270 | this._searchActive = true;
|
271 | let cells = this.widget.content.widgets;
|
272 | this._query = query;
|
273 | this._filters = {
|
274 | output: false,
|
275 | selection: false,
|
276 | ...(filters !== null && filters !== void 0 ? filters : {})
|
277 | };
|
278 | this._onSelection = this._filters.selection;
|
279 | const currentProviderIndex = this.widget.content.activeCellIndex;
|
280 |
|
281 | this._searchProviders = await Promise.all(cells.map(async (cell, index) => {
|
282 | const cellSearchProvider = createCellSearchProvider(cell);
|
283 | await cellSearchProvider.setIsActive(!this._filters.selection ||
|
284 | this.widget.content.isSelectedOrActive(cell));
|
285 | if (this._onSelection &&
|
286 | this._selectionSearchMode === 'text' &&
|
287 | index === currentProviderIndex) {
|
288 | if (this._textSelection) {
|
289 | await cellSearchProvider.setSearchSelection(this._textSelection);
|
290 | }
|
291 | }
|
292 | await cellSearchProvider.startQuery(query, this._filters);
|
293 | return cellSearchProvider;
|
294 | }));
|
295 | this._currentProviderIndex = currentProviderIndex;
|
296 |
|
297 |
|
298 |
|
299 |
|
300 |
|
301 |
|
302 |
|
303 | await this.highlightNext(true, {
|
304 | from: 'selection-start',
|
305 | scroll: false,
|
306 | select: false
|
307 | });
|
308 | return Promise.resolve();
|
309 | }
|
310 | |
311 |
|
312 |
|
313 | async endQuery() {
|
314 | await Promise.all(this._searchProviders.map(provider => {
|
315 | return provider.endQuery().then(() => {
|
316 | provider.dispose();
|
317 | });
|
318 | }));
|
319 | this._searchActive = false;
|
320 | this._searchProviders.length = 0;
|
321 | this._currentProviderIndex = null;
|
322 | }
|
323 | |
324 |
|
325 |
|
326 |
|
327 |
|
328 |
|
329 |
|
330 |
|
331 | async replaceCurrentMatch(newText, loop = true, options) {
|
332 | let replaceOccurred = false;
|
333 | const unrenderMarkdownCell = async (highlightNext = false) => {
|
334 | var _a;
|
335 |
|
336 | const activeCell = (_a = this.widget) === null || _a === void 0 ? void 0 : _a.content.activeCell;
|
337 | if ((activeCell === null || activeCell === void 0 ? void 0 : activeCell.model.type) === 'markdown' &&
|
338 | activeCell.rendered) {
|
339 | activeCell.rendered = false;
|
340 | if (highlightNext) {
|
341 | await this.highlightNext(loop);
|
342 | }
|
343 | }
|
344 | };
|
345 | if (this._currentProviderIndex !== null) {
|
346 | await unrenderMarkdownCell();
|
347 | const searchEngine = this._searchProviders[this._currentProviderIndex];
|
348 | replaceOccurred = await searchEngine.replaceCurrentMatch(newText, false, options);
|
349 | if (searchEngine.currentMatchIndex === null) {
|
350 |
|
351 | await this.highlightNext(loop);
|
352 | }
|
353 | }
|
354 |
|
355 |
|
356 | await unrenderMarkdownCell(true);
|
357 | return replaceOccurred;
|
358 | }
|
359 | |
360 |
|
361 |
|
362 |
|
363 |
|
364 |
|
365 |
|
366 | async replaceAllMatches(newText, options) {
|
367 | const replacementOccurred = await Promise.all(this._searchProviders.map(provider => {
|
368 | return provider.replaceAllMatches(newText, options);
|
369 | }));
|
370 | return replacementOccurred.includes(true);
|
371 | }
|
372 | async validateFilter(name, value) {
|
373 | if (name !== 'output') {
|
374 |
|
375 | return value;
|
376 | }
|
377 |
|
378 | if (value &&
|
379 | this.widget.content.widgets.some(w => w instanceof CodeCell && w.isPlaceholder())) {
|
380 | const trans = this.translator.load('jupyterlab');
|
381 | const reply = await showDialog({
|
382 | title: trans.__('Confirmation'),
|
383 | body: trans.__('Searching outputs is expensive and requires to first rendered all outputs. Are you sure you want to search in the cell outputs?'),
|
384 | buttons: [
|
385 | Dialog.cancelButton({ label: trans.__('Cancel') }),
|
386 | Dialog.okButton({ label: trans.__('Ok') })
|
387 | ]
|
388 | });
|
389 | if (reply.button.accept) {
|
390 | this.widget.content.widgets.forEach((w, i) => {
|
391 | if (w instanceof CodeCell && w.isPlaceholder()) {
|
392 | this.widget.content.renderCellOutputs(i);
|
393 | }
|
394 | });
|
395 | }
|
396 | else {
|
397 | return false;
|
398 | }
|
399 | }
|
400 | return value;
|
401 | }
|
402 | _addCellProvider(index) {
|
403 | var _a, _b;
|
404 | const cell = this.widget.content.widgets[index];
|
405 | const cellSearchProvider = createCellSearchProvider(cell);
|
406 | ArrayExt.insert(this._searchProviders, index, cellSearchProvider);
|
407 | void cellSearchProvider
|
408 | .setIsActive(!((_b = (_a = this._filters) === null || _a === void 0 ? void 0 : _a.selection) !== null && _b !== void 0 ? _b : false) ||
|
409 | this.widget.content.isSelectedOrActive(cell))
|
410 | .then(() => {
|
411 | if (this._searchActive) {
|
412 | void cellSearchProvider.startQuery(this._query, this._filters);
|
413 | }
|
414 | });
|
415 | }
|
416 | _removeCellProvider(index) {
|
417 | const provider = ArrayExt.removeAt(this._searchProviders, index);
|
418 | provider === null || provider === void 0 ? void 0 : provider.dispose();
|
419 | }
|
420 | async _onCellsChanged(cells, changes) {
|
421 | switch (changes.type) {
|
422 | case 'add':
|
423 | changes.newValues.forEach((model, index) => {
|
424 | this._addCellProvider(changes.newIndex + index);
|
425 | });
|
426 | break;
|
427 | case 'move':
|
428 | ArrayExt.move(this._searchProviders, changes.oldIndex, changes.newIndex);
|
429 | break;
|
430 | case 'remove':
|
431 | for (let index = 0; index < changes.oldValues.length; index++) {
|
432 | this._removeCellProvider(changes.oldIndex);
|
433 | }
|
434 | break;
|
435 | case 'set':
|
436 | changes.newValues.forEach((model, index) => {
|
437 | this._addCellProvider(changes.newIndex + index);
|
438 | this._removeCellProvider(changes.newIndex + index + 1);
|
439 | });
|
440 | break;
|
441 | }
|
442 | this._stateChanged.emit();
|
443 | }
|
444 | async _stepNext(reverse = false, loop = false, options) {
|
445 | const activateNewMatch = async (match) => {
|
446 | var _a;
|
447 | const shouldScroll = (_a = options === null || options === void 0 ? void 0 : options.scroll) !== null && _a !== void 0 ? _a : true;
|
448 | if (!shouldScroll) {
|
449 |
|
450 | return;
|
451 | }
|
452 | this._selectionLock = true;
|
453 | if (this.widget.content.activeCellIndex !== this._currentProviderIndex) {
|
454 | this.widget.content.activeCellIndex = this._currentProviderIndex;
|
455 | }
|
456 | if (this.widget.content.activeCellIndex === -1) {
|
457 | console.warn('No active cell (no cells or no model), aborting search');
|
458 | this._selectionLock = false;
|
459 | return;
|
460 | }
|
461 | const activeCell = this.widget.content.activeCell;
|
462 | if (!activeCell.inViewport) {
|
463 | try {
|
464 | await this.widget.content.scrollToItem(this._currentProviderIndex);
|
465 | }
|
466 | catch (error) {
|
467 |
|
468 | }
|
469 | }
|
470 |
|
471 | if (activeCell.inputHidden) {
|
472 | activeCell.inputHidden = false;
|
473 | }
|
474 | if (!activeCell.inViewport) {
|
475 | this._selectionLock = false;
|
476 |
|
477 | return;
|
478 | }
|
479 | await activeCell.ready;
|
480 | const editor = activeCell.editor;
|
481 | editor.revealPosition(editor.getPositionAt(match.position));
|
482 | this._selectionLock = false;
|
483 | };
|
484 | if (this._currentProviderIndex === null) {
|
485 | this._currentProviderIndex = this.widget.content.activeCellIndex;
|
486 | }
|
487 |
|
488 |
|
489 |
|
490 | if (reverse && this.widget.content.mode === 'command') {
|
491 | const searchEngine = this._searchProviders[this._currentProviderIndex];
|
492 | const currentMatch = searchEngine.getCurrentMatch();
|
493 | if (!currentMatch) {
|
494 | this._currentProviderIndex -= 1;
|
495 | }
|
496 | if (loop) {
|
497 | this._currentProviderIndex =
|
498 | (this._currentProviderIndex + this._searchProviders.length) %
|
499 | this._searchProviders.length;
|
500 | }
|
501 | }
|
502 | const startIndex = this._currentProviderIndex;
|
503 | do {
|
504 | const searchEngine = this._searchProviders[this._currentProviderIndex];
|
505 | const match = reverse
|
506 | ? await searchEngine.highlightPrevious(false, options)
|
507 | : await searchEngine.highlightNext(false, options);
|
508 | if (match) {
|
509 | await activateNewMatch(match);
|
510 | return match;
|
511 | }
|
512 | else {
|
513 | this._currentProviderIndex =
|
514 | this._currentProviderIndex + (reverse ? -1 : 1);
|
515 | if (loop) {
|
516 | this._currentProviderIndex =
|
517 | (this._currentProviderIndex + this._searchProviders.length) %
|
518 | this._searchProviders.length;
|
519 | }
|
520 | }
|
521 | } while (loop
|
522 | ?
|
523 | this._currentProviderIndex !== startIndex
|
524 | : 0 <= this._currentProviderIndex &&
|
525 | this._currentProviderIndex < this._searchProviders.length);
|
526 | if (loop) {
|
527 |
|
528 | const searchEngine = this._searchProviders[startIndex];
|
529 | const match = reverse
|
530 | ? await searchEngine.highlightPrevious(false, options)
|
531 | : await searchEngine.highlightNext(false, options);
|
532 | if (match) {
|
533 | await activateNewMatch(match);
|
534 | return match;
|
535 | }
|
536 | }
|
537 | this._currentProviderIndex = null;
|
538 | return null;
|
539 | }
|
540 | async _onActiveCellChanged() {
|
541 | if (this._delayedActiveCellChangeHandler !== null) {
|
542 |
|
543 |
|
544 | clearTimeout(this._delayedActiveCellChangeHandler);
|
545 | this._delayedActiveCellChangeHandler = null;
|
546 | }
|
547 | if (this.widget.content.activeCellIndex !== this._currentProviderIndex) {
|
548 |
|
549 |
|
550 |
|
551 |
|
552 |
|
553 | this._delayedActiveCellChangeHandler = window.setTimeout(() => {
|
554 | this.delayedActiveCellChangeHandlerReady =
|
555 | this._handleHighlightsAfterActiveCellChange();
|
556 | }, 0);
|
557 | }
|
558 | this._observeActiveCell();
|
559 | }
|
560 | async _handleHighlightsAfterActiveCellChange() {
|
561 | if (this._onSelection) {
|
562 | const previousProviderCell = this._currentProviderIndex !== null &&
|
563 | this._currentProviderIndex < this.widget.content.widgets.length
|
564 | ? this.widget.content.widgets[this._currentProviderIndex]
|
565 | : null;
|
566 | const previousProviderInCurrentSelection = previousProviderCell &&
|
567 | this.widget.content.isSelectedOrActive(previousProviderCell);
|
568 | if (!previousProviderInCurrentSelection) {
|
569 | await this._updateCellSelection();
|
570 |
|
571 | await this.clearHighlight();
|
572 |
|
573 |
|
574 |
|
575 | this._currentProviderIndex = this.widget.content.activeCellIndex;
|
576 | }
|
577 | }
|
578 | await this._ensureCurrentMatch();
|
579 | }
|
580 | |
581 |
|
582 |
|
583 |
|
584 | async _ensureCurrentMatch() {
|
585 | if (this._currentProviderIndex !== null) {
|
586 | const searchEngine = this._searchProviders[this._currentProviderIndex];
|
587 | if (!searchEngine) {
|
588 |
|
589 | return;
|
590 | }
|
591 | const currentMatch = searchEngine.getCurrentMatch();
|
592 | if (!currentMatch && this.matchesCount) {
|
593 |
|
594 |
|
595 | await this.highlightNext(true, {
|
596 | from: 'start',
|
597 | scroll: false,
|
598 | select: false
|
599 | });
|
600 | }
|
601 | }
|
602 | }
|
603 | _observeActiveCell() {
|
604 | var _a;
|
605 | const editor = (_a = this.widget.content.activeCell) === null || _a === void 0 ? void 0 : _a.editor;
|
606 | if (!editor) {
|
607 | return;
|
608 | }
|
609 | this._stopObservingLastCell();
|
610 | editor.model.selections.changed.connect(this._setSelectedLines, this);
|
611 | this._editorSelectionsObservable = editor.model.selections;
|
612 | }
|
613 | _stopObservingLastCell() {
|
614 | if (this._editorSelectionsObservable) {
|
615 | this._editorSelectionsObservable.changed.disconnect(this._setSelectedLines, this);
|
616 | }
|
617 | }
|
618 | _setSelectedLines() {
|
619 | var _a;
|
620 | const editor = (_a = this.widget.content.activeCell) === null || _a === void 0 ? void 0 : _a.editor;
|
621 | if (!editor) {
|
622 | return;
|
623 | }
|
624 | const selection = editor.getSelection();
|
625 | const { start, end } = selection;
|
626 | const newLines = end.line === start.line && end.column === start.column
|
627 | ? 0
|
628 | : end.line - start.line + 1;
|
629 | this._textSelection = selection;
|
630 | if (newLines !== this._selectedLines) {
|
631 | this._selectedLines = newLines;
|
632 | this._updateSelectionMode();
|
633 | }
|
634 | this._filtersChanged.emit();
|
635 | }
|
636 | |
637 |
|
638 |
|
639 | async _setEnginesSelectionSearchMode() {
|
640 | let textMode;
|
641 | if (!this._onSelection) {
|
642 |
|
643 | textMode = false;
|
644 | }
|
645 | else {
|
646 |
|
647 |
|
648 |
|
649 | textMode = this._selectionSearchMode === 'text';
|
650 | }
|
651 | if (this._selectionLock) {
|
652 | return;
|
653 | }
|
654 |
|
655 | await Promise.all(this._searchProviders.map((provider, index) => {
|
656 | const isCurrent = this.widget.content.activeCellIndex === index;
|
657 | provider.setProtectSelection(isCurrent && this._onSelection);
|
658 | return provider.setSearchSelection(isCurrent && textMode ? this._textSelection : null);
|
659 | }));
|
660 | }
|
661 | async _onCellSelectionChanged() {
|
662 | if (this._delayedActiveCellChangeHandler !== null) {
|
663 |
|
664 |
|
665 |
|
666 | clearTimeout(this._delayedActiveCellChangeHandler);
|
667 | this._delayedActiveCellChangeHandler = null;
|
668 | }
|
669 | await this._updateCellSelection();
|
670 | if (this._currentProviderIndex === null) {
|
671 |
|
672 | const firstSelectedCellIndex = this.widget.content.widgets.findIndex(cell => this.widget.content.isSelectedOrActive(cell));
|
673 | this._currentProviderIndex = firstSelectedCellIndex;
|
674 | }
|
675 | await this._ensureCurrentMatch();
|
676 | }
|
677 | async _updateCellSelection() {
|
678 | const cells = this.widget.content.widgets;
|
679 | let selectedCells = 0;
|
680 | await Promise.all(cells.map(async (cell, index) => {
|
681 | const provider = this._searchProviders[index];
|
682 | const isSelected = this.widget.content.isSelectedOrActive(cell);
|
683 | if (isSelected) {
|
684 | selectedCells += 1;
|
685 | }
|
686 | if (provider && this._onSelection) {
|
687 | await provider.setIsActive(isSelected);
|
688 | }
|
689 | }));
|
690 | if (selectedCells !== this._selectedCells) {
|
691 | this._selectedCells = selectedCells;
|
692 | this._updateSelectionMode();
|
693 | }
|
694 | this._filtersChanged.emit();
|
695 | }
|
696 | }
|
697 |
|
\ | No newline at end of file |