@itwin/presentation-frontend 4.5.0-dev.9 → 4.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (126) hide show
  1. package/CHANGELOG.md +63 -1
  2. package/LICENSE.md +1 -1
  3. package/README.md +1 -1
  4. package/lib/cjs/presentation-frontend/ConnectivityInformationProvider.d.ts.map +1 -1
  5. package/lib/cjs/presentation-frontend/ConnectivityInformationProvider.js +10 -6
  6. package/lib/cjs/presentation-frontend/ConnectivityInformationProvider.js.map +1 -1
  7. package/lib/cjs/presentation-frontend/Diagnostics.d.ts.map +1 -1
  8. package/lib/cjs/presentation-frontend/Diagnostics.js +18 -13
  9. package/lib/cjs/presentation-frontend/Diagnostics.js.map +1 -1
  10. package/lib/cjs/presentation-frontend/FrontendLoggerCategory.js +3 -3
  11. package/lib/cjs/presentation-frontend/FrontendLoggerCategory.js.map +1 -1
  12. package/lib/cjs/presentation-frontend/IpcRequestsHandler.d.ts.map +1 -1
  13. package/lib/cjs/presentation-frontend/IpcRequestsHandler.js +3 -3
  14. package/lib/cjs/presentation-frontend/IpcRequestsHandler.js.map +1 -1
  15. package/lib/cjs/presentation-frontend/LocalizationHelper.js +3 -3
  16. package/lib/cjs/presentation-frontend/LocalizationHelper.js.map +1 -1
  17. package/lib/cjs/presentation-frontend/Presentation.d.ts +1 -1
  18. package/lib/cjs/presentation-frontend/Presentation.d.ts.map +1 -1
  19. package/lib/cjs/presentation-frontend/Presentation.js +36 -21
  20. package/lib/cjs/presentation-frontend/Presentation.js.map +1 -1
  21. package/lib/cjs/presentation-frontend/PresentationManager.d.ts +84 -21
  22. package/lib/cjs/presentation-frontend/PresentationManager.d.ts.map +1 -1
  23. package/lib/cjs/presentation-frontend/PresentationManager.js +245 -154
  24. package/lib/cjs/presentation-frontend/PresentationManager.js.map +1 -1
  25. package/lib/cjs/presentation-frontend/RulesetManager.d.ts.map +1 -1
  26. package/lib/cjs/presentation-frontend/RulesetManager.js +11 -7
  27. package/lib/cjs/presentation-frontend/RulesetManager.js.map +1 -1
  28. package/lib/cjs/presentation-frontend/RulesetVariablesManager.d.ts.map +1 -1
  29. package/lib/cjs/presentation-frontend/RulesetVariablesManager.js +53 -31
  30. package/lib/cjs/presentation-frontend/RulesetVariablesManager.js.map +1 -1
  31. package/lib/cjs/presentation-frontend/StreamedResponseGenerator.d.ts +30 -0
  32. package/lib/cjs/presentation-frontend/StreamedResponseGenerator.d.ts.map +1 -0
  33. package/lib/cjs/presentation-frontend/StreamedResponseGenerator.js +117 -0
  34. package/lib/cjs/presentation-frontend/StreamedResponseGenerator.js.map +1 -0
  35. package/lib/cjs/presentation-frontend/favorite-properties/FavoritePropertiesManager.d.ts +33 -4
  36. package/lib/cjs/presentation-frontend/favorite-properties/FavoritePropertiesManager.d.ts.map +1 -1
  37. package/lib/cjs/presentation-frontend/favorite-properties/FavoritePropertiesManager.js +172 -67
  38. package/lib/cjs/presentation-frontend/favorite-properties/FavoritePropertiesManager.js.map +1 -1
  39. package/lib/cjs/presentation-frontend/favorite-properties/FavoritePropertiesStorage.d.ts.map +1 -1
  40. package/lib/cjs/presentation-frontend/favorite-properties/FavoritePropertiesStorage.js +54 -25
  41. package/lib/cjs/presentation-frontend/favorite-properties/FavoritePropertiesStorage.js.map +1 -1
  42. package/lib/cjs/presentation-frontend/selection/HiliteSetProvider.d.ts.map +1 -1
  43. package/lib/cjs/presentation-frontend/selection/HiliteSetProvider.js +23 -13
  44. package/lib/cjs/presentation-frontend/selection/HiliteSetProvider.js.map +1 -1
  45. package/lib/cjs/presentation-frontend/selection/ISelectionProvider.js +3 -3
  46. package/lib/cjs/presentation-frontend/selection/ISelectionProvider.js.map +1 -1
  47. package/lib/cjs/presentation-frontend/selection/SelectionChangeEvent.d.ts.map +1 -1
  48. package/lib/cjs/presentation-frontend/selection/SelectionChangeEvent.js +3 -3
  49. package/lib/cjs/presentation-frontend/selection/SelectionChangeEvent.js.map +1 -1
  50. package/lib/cjs/presentation-frontend/selection/SelectionHandler.d.ts.map +1 -1
  51. package/lib/cjs/presentation-frontend/selection/SelectionHandler.js +15 -9
  52. package/lib/cjs/presentation-frontend/selection/SelectionHandler.js.map +1 -1
  53. package/lib/cjs/presentation-frontend/selection/SelectionHelper.d.ts.map +1 -1
  54. package/lib/cjs/presentation-frontend/selection/SelectionHelper.js +7 -5
  55. package/lib/cjs/presentation-frontend/selection/SelectionHelper.js.map +1 -1
  56. package/lib/cjs/presentation-frontend/selection/SelectionManager.d.ts +22 -3
  57. package/lib/cjs/presentation-frontend/selection/SelectionManager.d.ts.map +1 -1
  58. package/lib/cjs/presentation-frontend/selection/SelectionManager.js +295 -75
  59. package/lib/cjs/presentation-frontend/selection/SelectionManager.js.map +1 -1
  60. package/lib/cjs/presentation-frontend/selection/SelectionScopesManager.d.ts.map +1 -1
  61. package/lib/cjs/presentation-frontend/selection/SelectionScopesManager.js +25 -14
  62. package/lib/cjs/presentation-frontend/selection/SelectionScopesManager.js.map +1 -1
  63. package/lib/cjs/presentation-frontend.js +3 -3
  64. package/lib/cjs/presentation-frontend.js.map +1 -1
  65. package/lib/esm/presentation-frontend/ConnectivityInformationProvider.d.ts.map +1 -1
  66. package/lib/esm/presentation-frontend/ConnectivityInformationProvider.js +10 -6
  67. package/lib/esm/presentation-frontend/ConnectivityInformationProvider.js.map +1 -1
  68. package/lib/esm/presentation-frontend/Diagnostics.d.ts.map +1 -1
  69. package/lib/esm/presentation-frontend/Diagnostics.js +18 -13
  70. package/lib/esm/presentation-frontend/Diagnostics.js.map +1 -1
  71. package/lib/esm/presentation-frontend/FrontendLoggerCategory.js +3 -3
  72. package/lib/esm/presentation-frontend/FrontendLoggerCategory.js.map +1 -1
  73. package/lib/esm/presentation-frontend/IpcRequestsHandler.d.ts.map +1 -1
  74. package/lib/esm/presentation-frontend/IpcRequestsHandler.js +3 -3
  75. package/lib/esm/presentation-frontend/IpcRequestsHandler.js.map +1 -1
  76. package/lib/esm/presentation-frontend/LocalizationHelper.js +3 -3
  77. package/lib/esm/presentation-frontend/LocalizationHelper.js.map +1 -1
  78. package/lib/esm/presentation-frontend/Presentation.d.ts +1 -1
  79. package/lib/esm/presentation-frontend/Presentation.d.ts.map +1 -1
  80. package/lib/esm/presentation-frontend/Presentation.js +36 -21
  81. package/lib/esm/presentation-frontend/Presentation.js.map +1 -1
  82. package/lib/esm/presentation-frontend/PresentationManager.d.ts +84 -21
  83. package/lib/esm/presentation-frontend/PresentationManager.d.ts.map +1 -1
  84. package/lib/esm/presentation-frontend/PresentationManager.js +244 -152
  85. package/lib/esm/presentation-frontend/PresentationManager.js.map +1 -1
  86. package/lib/esm/presentation-frontend/RulesetManager.d.ts.map +1 -1
  87. package/lib/esm/presentation-frontend/RulesetManager.js +11 -7
  88. package/lib/esm/presentation-frontend/RulesetManager.js.map +1 -1
  89. package/lib/esm/presentation-frontend/RulesetVariablesManager.d.ts.map +1 -1
  90. package/lib/esm/presentation-frontend/RulesetVariablesManager.js +53 -31
  91. package/lib/esm/presentation-frontend/RulesetVariablesManager.js.map +1 -1
  92. package/lib/esm/presentation-frontend/StreamedResponseGenerator.d.ts +30 -0
  93. package/lib/esm/presentation-frontend/StreamedResponseGenerator.d.ts.map +1 -0
  94. package/lib/esm/presentation-frontend/StreamedResponseGenerator.js +113 -0
  95. package/lib/esm/presentation-frontend/StreamedResponseGenerator.js.map +1 -0
  96. package/lib/esm/presentation-frontend/favorite-properties/FavoritePropertiesManager.d.ts +33 -4
  97. package/lib/esm/presentation-frontend/favorite-properties/FavoritePropertiesManager.d.ts.map +1 -1
  98. package/lib/esm/presentation-frontend/favorite-properties/FavoritePropertiesManager.js +172 -67
  99. package/lib/esm/presentation-frontend/favorite-properties/FavoritePropertiesManager.js.map +1 -1
  100. package/lib/esm/presentation-frontend/favorite-properties/FavoritePropertiesStorage.d.ts.map +1 -1
  101. package/lib/esm/presentation-frontend/favorite-properties/FavoritePropertiesStorage.js +54 -25
  102. package/lib/esm/presentation-frontend/favorite-properties/FavoritePropertiesStorage.js.map +1 -1
  103. package/lib/esm/presentation-frontend/selection/HiliteSetProvider.d.ts.map +1 -1
  104. package/lib/esm/presentation-frontend/selection/HiliteSetProvider.js +24 -14
  105. package/lib/esm/presentation-frontend/selection/HiliteSetProvider.js.map +1 -1
  106. package/lib/esm/presentation-frontend/selection/ISelectionProvider.js +3 -3
  107. package/lib/esm/presentation-frontend/selection/ISelectionProvider.js.map +1 -1
  108. package/lib/esm/presentation-frontend/selection/SelectionChangeEvent.d.ts.map +1 -1
  109. package/lib/esm/presentation-frontend/selection/SelectionChangeEvent.js +3 -3
  110. package/lib/esm/presentation-frontend/selection/SelectionChangeEvent.js.map +1 -1
  111. package/lib/esm/presentation-frontend/selection/SelectionHandler.d.ts.map +1 -1
  112. package/lib/esm/presentation-frontend/selection/SelectionHandler.js +15 -9
  113. package/lib/esm/presentation-frontend/selection/SelectionHandler.js.map +1 -1
  114. package/lib/esm/presentation-frontend/selection/SelectionHelper.d.ts.map +1 -1
  115. package/lib/esm/presentation-frontend/selection/SelectionHelper.js +7 -5
  116. package/lib/esm/presentation-frontend/selection/SelectionHelper.js.map +1 -1
  117. package/lib/esm/presentation-frontend/selection/SelectionManager.d.ts +22 -3
  118. package/lib/esm/presentation-frontend/selection/SelectionManager.d.ts.map +1 -1
  119. package/lib/esm/presentation-frontend/selection/SelectionManager.js +295 -75
  120. package/lib/esm/presentation-frontend/selection/SelectionManager.js.map +1 -1
  121. package/lib/esm/presentation-frontend/selection/SelectionScopesManager.d.ts.map +1 -1
  122. package/lib/esm/presentation-frontend/selection/SelectionScopesManager.js +25 -14
  123. package/lib/esm/presentation-frontend/selection/SelectionScopesManager.js.map +1 -1
  124. package/lib/esm/presentation-frontend.js +3 -3
  125. package/lib/esm/presentation-frontend.js.map +1 -1
  126. package/package.json +20 -16
@@ -1,16 +1,19 @@
1
1
  "use strict";
2
2
  /*---------------------------------------------------------------------------------------------
3
- * Copyright (c) Bentley Systems, Incorporated. All rights reserved.
4
- * See LICENSE.md in the project root for license terms and full copyright notice.
5
- *--------------------------------------------------------------------------------------------*/
3
+ * Copyright (c) Bentley Systems, Incorporated. All rights reserved.
4
+ * See LICENSE.md in the project root for license terms and full copyright notice.
5
+ *--------------------------------------------------------------------------------------------*/
6
6
  /** @packageDocumentation
7
7
  * @module UnifiedSelection
8
8
  */
9
9
  Object.defineProperty(exports, "__esModule", { value: true });
10
10
  exports.ToolSelectionSyncHandler = exports.TRANSIENT_ELEMENT_CLASSNAME = exports.SelectionManager = void 0;
11
+ const rxjs_1 = require("rxjs");
11
12
  const core_bentley_1 = require("@itwin/core-bentley");
12
13
  const core_frontend_1 = require("@itwin/core-frontend");
13
14
  const presentation_common_1 = require("@itwin/presentation-common");
15
+ const unified_selection_1 = require("@itwin/unified-selection");
16
+ const Presentation_1 = require("../Presentation");
14
17
  const HiliteSetProvider_1 = require("./HiliteSetProvider");
15
18
  const SelectionChangeEvent_1 = require("./SelectionChangeEvent");
16
19
  const SelectionScopesManager_1 = require("./SelectionScopesManager");
@@ -23,31 +26,43 @@ class SelectionManager {
23
26
  * Creates an instance of SelectionManager.
24
27
  */
25
28
  constructor(props) {
26
- this._selectionContainerMap = new Map();
27
29
  this._imodelToolSelectionSyncHandlers = new Map();
28
30
  this._hiliteSetProviders = new Map();
31
+ this._knownIModels = new Map();
32
+ this._currentSelection = new CurrentSelectionStorage();
33
+ this._selectionChanges = new rxjs_1.Subject();
34
+ this._listeners = [];
29
35
  this.selectionChange = new SelectionChangeEvent_1.SelectionChangeEvent();
30
36
  this.scopes = props.scopes;
31
- core_frontend_1.IModelConnection.onClose.addListener((imodel) => {
37
+ this._selectionStorage = props.selectionStorage ?? (0, unified_selection_1.createStorage)();
38
+ this._ownsStorage = props.selectionStorage === undefined;
39
+ this._selectionStorage.selectionChangeEvent.addListener((args) => this._selectionChanges.next(args));
40
+ this._selectionEventsSubscription = this.streamSelectionEvents();
41
+ this._listeners.push(core_frontend_1.IModelConnection.onOpen.addListener((imodel) => {
42
+ this._knownIModels.set(imodel.key, imodel);
43
+ }));
44
+ this._listeners.push(core_frontend_1.IModelConnection.onClose.addListener((imodel) => {
32
45
  this.onConnectionClose(imodel);
33
- });
46
+ }));
47
+ }
48
+ dispose() {
49
+ this._selectionEventsSubscription.unsubscribe();
50
+ this._listeners.forEach((dispose) => dispose());
34
51
  }
35
52
  onConnectionClose(imodel) {
36
- this.clearSelection("Connection Close Event", imodel);
37
- this._selectionContainerMap.delete(imodel);
38
53
  this._hiliteSetProviders.delete(imodel);
39
- }
40
- getContainer(imodel) {
41
- let selectionContainer = this._selectionContainerMap.get(imodel);
42
- if (!selectionContainer) {
43
- selectionContainer = new SelectionContainer();
44
- this._selectionContainerMap.set(imodel, selectionContainer);
54
+ this._knownIModels.delete(imodel.key);
55
+ this._currentSelection.clear(imodel.key);
56
+ if (this._ownsStorage) {
57
+ this.clearSelection("Connection Close Event", imodel);
58
+ this._selectionStorage.clearStorage({ iModelKey: imodel.key });
45
59
  }
46
- return selectionContainer;
47
60
  }
48
61
  /** @internal */
49
62
  // istanbul ignore next
50
- getToolSelectionSyncHandler(imodel) { return this._imodelToolSelectionSyncHandlers.get(imodel)?.handler; }
63
+ getToolSelectionSyncHandler(imodel) {
64
+ return this._imodelToolSelectionSyncHandlers.get(imodel)?.handler;
65
+ }
51
66
  /**
52
67
  * Request the manager to sync with imodel's tool selection (see `IModelConnection.selectionSet`).
53
68
  */
@@ -80,46 +95,57 @@ class SelectionManager {
80
95
  */
81
96
  suspendIModelToolSelectionSync(imodel) {
82
97
  const registration = this._imodelToolSelectionSyncHandlers.get(imodel);
83
- if (!registration)
98
+ if (!registration) {
84
99
  return { dispose: () => { } };
100
+ }
85
101
  const wasSuspended = registration.handler.isSuspended;
86
102
  registration.handler.isSuspended = true;
87
103
  return { dispose: () => (registration.handler.isSuspended = wasSuspended) };
88
104
  }
89
105
  /** Get the selection levels currently stored in this manager for the specified imodel */
90
106
  getSelectionLevels(imodel) {
91
- return this.getContainer(imodel).getSelectionLevels();
107
+ return this._selectionStorage.getSelectionLevels({ iModelKey: imodel.key });
92
108
  }
93
- /** Get the selection currently stored in this manager */
109
+ /**
110
+ * Get the selection currently stored in this manager
111
+ *
112
+ * @note Calling immediately after `add*`|`replace*`|`remove*`|`clear*` method call does not guarantee
113
+ * that returned `KeySet` will include latest changes. Listen for `selectionChange` event to get the
114
+ * latest selection after changes.
115
+ */
94
116
  getSelection(imodel, level = 0) {
95
- return this.getContainer(imodel).getSelection(level);
117
+ return this._currentSelection.getSelection(imodel.key, level);
96
118
  }
97
119
  handleEvent(evt) {
98
- const container = this.getContainer(evt.imodel);
99
- const selectedItemsSet = container.getSelection(evt.level);
100
- const guidBefore = selectedItemsSet.guid;
101
120
  switch (evt.changeType) {
102
121
  case SelectionChangeEvent_1.SelectionChangeType.Add:
103
- selectedItemsSet.add(evt.keys);
122
+ this._selectionStorage.addToSelection({
123
+ iModelKey: evt.imodel.key,
124
+ source: evt.source,
125
+ level: evt.level,
126
+ selectables: keysToSelectable(evt.imodel, evt.keys),
127
+ });
104
128
  break;
105
129
  case SelectionChangeEvent_1.SelectionChangeType.Remove:
106
- selectedItemsSet.delete(evt.keys);
130
+ this._selectionStorage.removeFromSelection({
131
+ iModelKey: evt.imodel.key,
132
+ source: evt.source,
133
+ level: evt.level,
134
+ selectables: keysToSelectable(evt.imodel, evt.keys),
135
+ });
107
136
  break;
108
137
  case SelectionChangeEvent_1.SelectionChangeType.Replace:
109
- if (selectedItemsSet.size !== evt.keys.size || !selectedItemsSet.hasAll(evt.keys)) {
110
- // note: the above check is only needed to avoid changing
111
- // guid of the keyset if we're replacing keyset with the same keys
112
- selectedItemsSet.clear().add(evt.keys);
113
- }
138
+ this._selectionStorage.replaceSelection({
139
+ iModelKey: evt.imodel.key,
140
+ source: evt.source,
141
+ level: evt.level,
142
+ selectables: keysToSelectable(evt.imodel, evt.keys),
143
+ });
114
144
  break;
115
145
  case SelectionChangeEvent_1.SelectionChangeType.Clear:
116
- selectedItemsSet.clear();
146
+ this._selectionStorage.clearSelection({ iModelKey: evt.imodel.key, source: evt.source, level: evt.level });
117
147
  break;
118
148
  }
119
- if (selectedItemsSet.guid === guidBefore)
120
- return;
121
- container.clear(evt.level + 1);
122
- this.selectionChange.raiseEvent(evt, this);
123
149
  }
124
150
  /**
125
151
  * Add keys to the selection
@@ -261,39 +287,33 @@ class SelectionManager {
261
287
  }
262
288
  return provider;
263
289
  }
264
- }
265
- exports.SelectionManager = SelectionManager;
266
- /** @internal */
267
- class SelectionContainer {
268
- constructor() {
269
- this._selectedItemsSetMap = new Map();
270
- }
271
- getSelection(level) {
272
- let selectedItemsSet = this._selectedItemsSetMap.get(level);
273
- if (!selectedItemsSet) {
274
- selectedItemsSet = new presentation_common_1.KeySet();
275
- this._selectedItemsSetMap.set(level, selectedItemsSet);
276
- }
277
- return selectedItemsSet;
278
- }
279
- getSelectionLevels() {
280
- const levels = new Array();
281
- for (const entry of this._selectedItemsSetMap.entries()) {
282
- if (!entry[1].isEmpty)
283
- levels.push(entry[0]);
284
- }
285
- return levels.sort();
286
- }
287
- clear(level) {
288
- const keys = this._selectedItemsSetMap.keys();
289
- for (const key of keys) {
290
- if (key >= level) {
291
- const selectedItemsSet = this._selectedItemsSetMap.get(key);
292
- selectedItemsSet.clear();
293
- }
294
- }
290
+ streamSelectionEvents() {
291
+ return this._selectionChanges
292
+ .pipe((0, rxjs_1.mergeMap)((args) => {
293
+ const currentSelectables = this._selectionStorage.getSelection({ iModelKey: args.iModelKey, level: args.level });
294
+ return this._currentSelection.computeSelection(args.iModelKey, args.level, currentSelectables, args.selectables).pipe((0, rxjs_1.mergeMap)(({ level, changedSelection }) => {
295
+ const imodel = this._knownIModels.get(args.iModelKey);
296
+ if (!imodel) {
297
+ return rxjs_1.EMPTY;
298
+ }
299
+ return (0, rxjs_1.of)({
300
+ imodel,
301
+ keys: changedSelection,
302
+ level,
303
+ source: args.source,
304
+ timestamp: args.timestamp,
305
+ changeType: getChangeType(args.changeType),
306
+ });
307
+ }));
308
+ }))
309
+ .subscribe({
310
+ next: (args) => {
311
+ this.selectionChange.raiseEvent(args, this);
312
+ },
313
+ });
295
314
  }
296
315
  }
316
+ exports.SelectionManager = SelectionManager;
297
317
  /** @internal */
298
318
  exports.TRANSIENT_ELEMENT_CLASSNAME = "/TRANSIENT";
299
319
  /** @internal */
@@ -304,12 +324,14 @@ class ToolSelectionSyncHandler {
304
324
  // eslint-disable-next-line @typescript-eslint/naming-convention
305
325
  this.onToolSelectionChanged = async (ev) => {
306
326
  // ignore selection change event if the handler is suspended
307
- if (this.isSuspended)
327
+ if (this.isSuspended) {
308
328
  return;
329
+ }
309
330
  // this component only cares about its own imodel
310
331
  const imodel = ev.set.iModel;
311
- if (imodel !== this._imodel)
332
+ if (imodel !== this._imodel) {
312
333
  return;
334
+ }
313
335
  // determine the level of selection changes
314
336
  // wip: may want to allow selecting at different levels?
315
337
  const selectionLevel = 0;
@@ -358,19 +380,24 @@ class ToolSelectionSyncHandler {
358
380
  this._imodelToolSelectionListenerDisposeFunc();
359
381
  }
360
382
  /** note: used only it tests */
361
- get pendingAsyncs() { return this._asyncsTracker.pendingAsyncs; }
383
+ get pendingAsyncs() {
384
+ return this._asyncsTracker.pendingAsyncs;
385
+ }
362
386
  }
363
387
  exports.ToolSelectionSyncHandler = ToolSelectionSyncHandler;
364
388
  const parseIds = (ids) => {
365
389
  let allPersistent = true;
366
390
  let allTransient = true;
367
391
  for (const id of core_bentley_1.Id64.iterable(ids)) {
368
- if (core_bentley_1.Id64.isTransient(id))
392
+ if (core_bentley_1.Id64.isTransient(id)) {
369
393
  allPersistent = false;
370
- else
394
+ }
395
+ else {
371
396
  allTransient = false;
372
- if (!allPersistent && !allTransient)
397
+ }
398
+ if (!allPersistent && !allTransient) {
373
399
  break;
400
+ }
374
401
  }
375
402
  // avoid making a copy if ids are only persistent or only transient
376
403
  if (allPersistent) {
@@ -384,16 +411,19 @@ const parseIds = (ids) => {
384
411
  const persistentElementIds = [];
385
412
  const transientElementIds = [];
386
413
  for (const id of core_bentley_1.Id64.iterable(ids)) {
387
- if (core_bentley_1.Id64.isTransient(id))
414
+ if (core_bentley_1.Id64.isTransient(id)) {
388
415
  transientElementIds.push(id);
389
- else
416
+ }
417
+ else {
390
418
  persistentElementIds.push(id);
419
+ }
391
420
  }
392
421
  return { persistent: persistentElementIds, transient: transientElementIds };
393
422
  };
394
423
  function addTransientKeys(transientIds, keys) {
395
- for (const id of core_bentley_1.Id64.iterable(transientIds))
424
+ for (const id of core_bentley_1.Id64.iterable(transientIds)) {
396
425
  keys.add({ className: exports.TRANSIENT_ELEMENT_CLASSNAME, id });
426
+ }
397
427
  }
398
428
  /** @internal */
399
429
  class ScopedSelectionChanger {
@@ -422,4 +452,194 @@ class ScopedSelectionChanger {
422
452
  this.manager.replaceSelection(this.name, this.imodel, keys, level);
423
453
  }
424
454
  }
455
+ /** Stores current selection in `KeySet` format per iModel. */
456
+ class CurrentSelectionStorage {
457
+ constructor() {
458
+ this._currentSelection = new Map();
459
+ }
460
+ getCurrentSelectionStorage(imodelKey) {
461
+ let storage = this._currentSelection.get(imodelKey);
462
+ if (!storage) {
463
+ storage = new IModelSelectionStorage();
464
+ this._currentSelection.set(imodelKey, storage);
465
+ }
466
+ return storage;
467
+ }
468
+ getSelection(imodelKey, level) {
469
+ return this.getCurrentSelectionStorage(imodelKey).getSelection(level);
470
+ }
471
+ clear(imodelKey) {
472
+ this._currentSelection.delete(imodelKey);
473
+ }
474
+ computeSelection(imodelKey, level, currSelectables, changedSelectables) {
475
+ return this.getCurrentSelectionStorage(imodelKey).computeSelection(level, currSelectables, changedSelectables);
476
+ }
477
+ }
478
+ /**
479
+ * Computes and stores current selection in `KeySet` format.
480
+ * It always stores result of latest resolved call to `computeSelection`.
481
+ */
482
+ class IModelSelectionStorage {
483
+ constructor() {
484
+ this._currentSelection = new Map();
485
+ }
486
+ getSelection(level) {
487
+ let entry = this._currentSelection.get(level);
488
+ if (!entry) {
489
+ entry = { value: new presentation_common_1.KeySet(), ongoingComputationDisposers: new Set() };
490
+ this._currentSelection.set(level, entry);
491
+ }
492
+ return entry.value;
493
+ }
494
+ clearSelections(level) {
495
+ const clearedLevels = [];
496
+ for (const [storedLevel] of this._currentSelection.entries()) {
497
+ if (storedLevel > level) {
498
+ clearedLevels.push(storedLevel);
499
+ }
500
+ }
501
+ clearedLevels.forEach((storedLevel) => {
502
+ const entry = this._currentSelection.get(storedLevel);
503
+ // istanbul ignore if
504
+ if (!entry) {
505
+ return;
506
+ }
507
+ for (const disposer of entry.ongoingComputationDisposers) {
508
+ disposer.next();
509
+ }
510
+ this._currentSelection.delete(storedLevel);
511
+ });
512
+ }
513
+ addDisposer(level, disposer) {
514
+ const entry = this._currentSelection.get(level);
515
+ if (!entry) {
516
+ this._currentSelection.set(level, { value: new presentation_common_1.KeySet(), ongoingComputationDisposers: new Set([disposer]) });
517
+ return;
518
+ }
519
+ entry.ongoingComputationDisposers.add(disposer);
520
+ }
521
+ setSelection(level, keys, disposer) {
522
+ const currEntry = this._currentSelection.get(level);
523
+ // istanbul ignore else
524
+ if (currEntry) {
525
+ currEntry.ongoingComputationDisposers.delete(disposer);
526
+ }
527
+ this._currentSelection.set(level, {
528
+ value: keys,
529
+ ongoingComputationDisposers: currEntry?.ongoingComputationDisposers ?? /* istanbul ignore next */ new Set(),
530
+ });
531
+ }
532
+ computeSelection(level, currSelectables, changedSelectables) {
533
+ this.clearSelections(level);
534
+ const prevComputationsDisposers = [...(this._currentSelection.get(level)?.ongoingComputationDisposers ?? [])];
535
+ const currDisposer = new rxjs_1.Subject();
536
+ this.addDisposer(level, currDisposer);
537
+ return (0, rxjs_1.defer)(async () => {
538
+ const convertedSelectables = [];
539
+ const [current, changed] = await Promise.all([
540
+ selectablesToKeys(currSelectables, convertedSelectables),
541
+ selectablesToKeys(changedSelectables, convertedSelectables),
542
+ ]);
543
+ const currentSelection = new presentation_common_1.KeySet([...current.keys, ...current.selectableKeys.flatMap((selectable) => selectable.keys)]);
544
+ const changedSelection = new presentation_common_1.KeySet([...changed.keys, ...changed.selectableKeys.flatMap((selectable) => selectable.keys)]);
545
+ return {
546
+ level,
547
+ currentSelection,
548
+ changedSelection,
549
+ };
550
+ }).pipe((0, rxjs_1.takeUntil)(currDisposer), (0, rxjs_1.tap)({
551
+ next: (val) => {
552
+ prevComputationsDisposers.forEach((disposer) => disposer.next());
553
+ this.setSelection(val.level, val.currentSelection, currDisposer);
554
+ },
555
+ }));
556
+ }
557
+ }
558
+ function keysToSelectable(imodel, keys) {
559
+ const selectables = [];
560
+ keys.forEach((key) => {
561
+ if ("id" in key) {
562
+ selectables.push(key);
563
+ return;
564
+ }
565
+ const customSelectable = {
566
+ identifier: key.pathFromRoot.join("/"),
567
+ data: key,
568
+ loadInstanceKeys: () => createInstanceKeysIterator(imodel, key),
569
+ };
570
+ selectables.push(customSelectable);
571
+ });
572
+ return selectables;
573
+ }
574
+ async function selectablesToKeys(selectables, convertedList) {
575
+ const keys = [];
576
+ const selectableKeys = [];
577
+ for (const [className, ids] of selectables.instanceKeys) {
578
+ for (const id of ids) {
579
+ keys.push({ id, className });
580
+ }
581
+ }
582
+ for (const [_, selectable] of selectables.custom) {
583
+ if (isNodeKey(selectable.data)) {
584
+ selectableKeys.push({ identifier: selectable.identifier, keys: [selectable.data] });
585
+ continue;
586
+ }
587
+ const converted = convertedList.find((con) => con.identifier === selectable.identifier);
588
+ if (converted) {
589
+ selectableKeys.push(converted);
590
+ continue;
591
+ }
592
+ const newConverted = { identifier: selectable.identifier, keys: [] };
593
+ convertedList.push(newConverted);
594
+ for await (const instanceKey of selectable.loadInstanceKeys()) {
595
+ newConverted.keys.push(instanceKey);
596
+ }
597
+ selectableKeys.push(newConverted);
598
+ }
599
+ return { keys, selectableKeys };
600
+ }
601
+ async function* createInstanceKeysIterator(imodel, nodeKey) {
602
+ if (presentation_common_1.NodeKey.isInstancesNodeKey(nodeKey)) {
603
+ for (const key of nodeKey.instanceKeys) {
604
+ yield key;
605
+ }
606
+ return;
607
+ }
608
+ const content = await Presentation_1.Presentation.presentation.getContentInstanceKeys({
609
+ imodel,
610
+ keys: new presentation_common_1.KeySet([nodeKey]),
611
+ rulesetOrId: {
612
+ id: "grouped-instances",
613
+ rules: [
614
+ {
615
+ ruleType: "Content",
616
+ specifications: [
617
+ {
618
+ specType: "SelectedNodeInstances",
619
+ },
620
+ ],
621
+ },
622
+ ],
623
+ },
624
+ });
625
+ for await (const key of content.items()) {
626
+ yield key;
627
+ }
628
+ }
629
+ function isNodeKey(data) {
630
+ const key = data;
631
+ return key.pathFromRoot !== undefined && key.type !== undefined;
632
+ }
633
+ function getChangeType(type) {
634
+ switch (type) {
635
+ case "add":
636
+ return SelectionChangeEvent_1.SelectionChangeType.Add;
637
+ case "remove":
638
+ return SelectionChangeEvent_1.SelectionChangeType.Remove;
639
+ case "replace":
640
+ return SelectionChangeEvent_1.SelectionChangeType.Replace;
641
+ case "clear":
642
+ return SelectionChangeEvent_1.SelectionChangeType.Clear;
643
+ }
644
+ }
425
645
  //# sourceMappingURL=SelectionManager.js.map