@itwin/presentation-frontend 4.0.0-dev.21 → 4.0.0-dev.23

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 (123) hide show
  1. package/lib/cjs/presentation-frontend/ConnectivityInformationProvider.d.ts +29 -29
  2. package/lib/cjs/presentation-frontend/ConnectivityInformationProvider.js +47 -47
  3. package/lib/cjs/presentation-frontend/ConnectivityInformationProvider.js.map +1 -1
  4. package/lib/cjs/presentation-frontend/Diagnostics.d.ts +14 -14
  5. package/lib/cjs/presentation-frontend/Diagnostics.js +61 -61
  6. package/lib/cjs/presentation-frontend/Diagnostics.js.map +1 -1
  7. package/lib/cjs/presentation-frontend/FrontendLoggerCategory.d.ts +12 -12
  8. package/lib/cjs/presentation-frontend/FrontendLoggerCategory.js +20 -20
  9. package/lib/cjs/presentation-frontend/FrontendLoggerCategory.js.map +1 -1
  10. package/lib/cjs/presentation-frontend/IpcRequestsHandler.d.ts +10 -10
  11. package/lib/cjs/presentation-frontend/IpcRequestsHandler.js +41 -41
  12. package/lib/cjs/presentation-frontend/IpcRequestsHandler.js.map +1 -1
  13. package/lib/cjs/presentation-frontend/LocalizationHelper.d.ts +10 -10
  14. package/lib/cjs/presentation-frontend/LocalizationHelper.js +31 -31
  15. package/lib/cjs/presentation-frontend/LocalizationHelper.js.map +1 -1
  16. package/lib/cjs/presentation-frontend/Presentation.d.ts +73 -73
  17. package/lib/cjs/presentation-frontend/Presentation.js +160 -160
  18. package/lib/cjs/presentation-frontend/Presentation.js.map +1 -1
  19. package/lib/cjs/presentation-frontend/PresentationManager.d.ts +186 -186
  20. package/lib/cjs/presentation-frontend/PresentationManager.js +436 -436
  21. package/lib/cjs/presentation-frontend/PresentationManager.js.map +1 -1
  22. package/lib/cjs/presentation-frontend/RulesetManager.d.ts +63 -63
  23. package/lib/cjs/presentation-frontend/RulesetManager.js +85 -85
  24. package/lib/cjs/presentation-frontend/RulesetManager.js.map +1 -1
  25. package/lib/cjs/presentation-frontend/RulesetVariablesManager.d.ts +143 -143
  26. package/lib/cjs/presentation-frontend/RulesetVariablesManager.js +195 -195
  27. package/lib/cjs/presentation-frontend/RulesetVariablesManager.js.map +1 -1
  28. package/lib/cjs/presentation-frontend/StateTracker.d.ts +38 -38
  29. package/lib/cjs/presentation-frontend/StateTracker.js +129 -129
  30. package/lib/cjs/presentation-frontend/StateTracker.js.map +1 -1
  31. package/lib/cjs/presentation-frontend/favorite-properties/FavoritePropertiesManager.d.ts +132 -132
  32. package/lib/cjs/presentation-frontend/favorite-properties/FavoritePropertiesManager.js +525 -525
  33. package/lib/cjs/presentation-frontend/favorite-properties/FavoritePropertiesManager.js.map +1 -1
  34. package/lib/cjs/presentation-frontend/favorite-properties/FavoritePropertiesStorage.d.ts +111 -111
  35. package/lib/cjs/presentation-frontend/favorite-properties/FavoritePropertiesStorage.js +293 -293
  36. package/lib/cjs/presentation-frontend/favorite-properties/FavoritePropertiesStorage.js.map +1 -1
  37. package/lib/cjs/presentation-frontend/selection/HiliteRules.json +172 -172
  38. package/lib/cjs/presentation-frontend/selection/HiliteSetProvider.d.ts +52 -52
  39. package/lib/cjs/presentation-frontend/selection/HiliteSetProvider.js +97 -97
  40. package/lib/cjs/presentation-frontend/selection/HiliteSetProvider.js.map +1 -1
  41. package/lib/cjs/presentation-frontend/selection/ISelectionProvider.d.ts +19 -19
  42. package/lib/cjs/presentation-frontend/selection/ISelectionProvider.js +9 -9
  43. package/lib/cjs/presentation-frontend/selection/ISelectionProvider.js.map +1 -1
  44. package/lib/cjs/presentation-frontend/selection/SelectionChangeEvent.d.ts +52 -52
  45. package/lib/cjs/presentation-frontend/selection/SelectionChangeEvent.js +33 -33
  46. package/lib/cjs/presentation-frontend/selection/SelectionChangeEvent.js.map +1 -1
  47. package/lib/cjs/presentation-frontend/selection/SelectionHandler.d.ts +103 -103
  48. package/lib/cjs/presentation-frontend/selection/SelectionHandler.js +108 -108
  49. package/lib/cjs/presentation-frontend/selection/SelectionHandler.js.map +1 -1
  50. package/lib/cjs/presentation-frontend/selection/SelectionHelper.d.ts +17 -17
  51. package/lib/cjs/presentation-frontend/selection/SelectionHelper.js +40 -40
  52. package/lib/cjs/presentation-frontend/selection/SelectionHelper.js.map +1 -1
  53. package/lib/cjs/presentation-frontend/selection/SelectionManager.d.ts +139 -139
  54. package/lib/cjs/presentation-frontend/selection/SelectionManager.js +414 -414
  55. package/lib/cjs/presentation-frontend/selection/SelectionManager.js.map +1 -1
  56. package/lib/cjs/presentation-frontend/selection/SelectionScopesManager.d.ts +59 -59
  57. package/lib/cjs/presentation-frontend/selection/SelectionScopesManager.js +91 -91
  58. package/lib/cjs/presentation-frontend/selection/SelectionScopesManager.js.map +1 -1
  59. package/lib/cjs/presentation-frontend.d.ts +34 -34
  60. package/lib/cjs/presentation-frontend.js +50 -50
  61. package/lib/cjs/presentation-frontend.js.map +1 -1
  62. package/lib/esm/presentation-frontend/ConnectivityInformationProvider.d.ts +29 -29
  63. package/lib/esm/presentation-frontend/ConnectivityInformationProvider.js +43 -43
  64. package/lib/esm/presentation-frontend/ConnectivityInformationProvider.js.map +1 -1
  65. package/lib/esm/presentation-frontend/Diagnostics.d.ts +14 -14
  66. package/lib/esm/presentation-frontend/Diagnostics.js +56 -56
  67. package/lib/esm/presentation-frontend/Diagnostics.js.map +1 -1
  68. package/lib/esm/presentation-frontend/FrontendLoggerCategory.d.ts +12 -12
  69. package/lib/esm/presentation-frontend/FrontendLoggerCategory.js +17 -17
  70. package/lib/esm/presentation-frontend/FrontendLoggerCategory.js.map +1 -1
  71. package/lib/esm/presentation-frontend/IpcRequestsHandler.d.ts +10 -10
  72. package/lib/esm/presentation-frontend/IpcRequestsHandler.js +37 -37
  73. package/lib/esm/presentation-frontend/IpcRequestsHandler.js.map +1 -1
  74. package/lib/esm/presentation-frontend/LocalizationHelper.d.ts +10 -10
  75. package/lib/esm/presentation-frontend/LocalizationHelper.js +27 -27
  76. package/lib/esm/presentation-frontend/LocalizationHelper.js.map +1 -1
  77. package/lib/esm/presentation-frontend/Presentation.d.ts +73 -73
  78. package/lib/esm/presentation-frontend/Presentation.js +156 -156
  79. package/lib/esm/presentation-frontend/Presentation.js.map +1 -1
  80. package/lib/esm/presentation-frontend/PresentationManager.d.ts +186 -186
  81. package/lib/esm/presentation-frontend/PresentationManager.js +431 -431
  82. package/lib/esm/presentation-frontend/PresentationManager.js.map +1 -1
  83. package/lib/esm/presentation-frontend/RulesetManager.d.ts +63 -63
  84. package/lib/esm/presentation-frontend/RulesetManager.js +81 -81
  85. package/lib/esm/presentation-frontend/RulesetManager.js.map +1 -1
  86. package/lib/esm/presentation-frontend/RulesetVariablesManager.d.ts +143 -143
  87. package/lib/esm/presentation-frontend/RulesetVariablesManager.js +191 -191
  88. package/lib/esm/presentation-frontend/RulesetVariablesManager.js.map +1 -1
  89. package/lib/esm/presentation-frontend/StateTracker.d.ts +38 -38
  90. package/lib/esm/presentation-frontend/StateTracker.js +125 -125
  91. package/lib/esm/presentation-frontend/StateTracker.js.map +1 -1
  92. package/lib/esm/presentation-frontend/favorite-properties/FavoritePropertiesManager.d.ts +132 -132
  93. package/lib/esm/presentation-frontend/favorite-properties/FavoritePropertiesManager.js +519 -519
  94. package/lib/esm/presentation-frontend/favorite-properties/FavoritePropertiesManager.js.map +1 -1
  95. package/lib/esm/presentation-frontend/favorite-properties/FavoritePropertiesStorage.d.ts +111 -111
  96. package/lib/esm/presentation-frontend/favorite-properties/FavoritePropertiesStorage.js +285 -285
  97. package/lib/esm/presentation-frontend/favorite-properties/FavoritePropertiesStorage.js.map +1 -1
  98. package/lib/esm/presentation-frontend/selection/HiliteRules.json +172 -172
  99. package/lib/esm/presentation-frontend/selection/HiliteSetProvider.d.ts +52 -52
  100. package/lib/esm/presentation-frontend/selection/HiliteSetProvider.js +93 -93
  101. package/lib/esm/presentation-frontend/selection/HiliteSetProvider.js.map +1 -1
  102. package/lib/esm/presentation-frontend/selection/ISelectionProvider.d.ts +19 -19
  103. package/lib/esm/presentation-frontend/selection/ISelectionProvider.js +8 -8
  104. package/lib/esm/presentation-frontend/selection/ISelectionProvider.js.map +1 -1
  105. package/lib/esm/presentation-frontend/selection/SelectionChangeEvent.d.ts +52 -52
  106. package/lib/esm/presentation-frontend/selection/SelectionChangeEvent.js +29 -29
  107. package/lib/esm/presentation-frontend/selection/SelectionChangeEvent.js.map +1 -1
  108. package/lib/esm/presentation-frontend/selection/SelectionHandler.d.ts +103 -103
  109. package/lib/esm/presentation-frontend/selection/SelectionHandler.js +104 -104
  110. package/lib/esm/presentation-frontend/selection/SelectionHandler.js.map +1 -1
  111. package/lib/esm/presentation-frontend/selection/SelectionHelper.d.ts +17 -17
  112. package/lib/esm/presentation-frontend/selection/SelectionHelper.js +36 -36
  113. package/lib/esm/presentation-frontend/selection/SelectionHelper.js.map +1 -1
  114. package/lib/esm/presentation-frontend/selection/SelectionManager.d.ts +139 -139
  115. package/lib/esm/presentation-frontend/selection/SelectionManager.js +409 -409
  116. package/lib/esm/presentation-frontend/selection/SelectionManager.js.map +1 -1
  117. package/lib/esm/presentation-frontend/selection/SelectionScopesManager.d.ts +59 -59
  118. package/lib/esm/presentation-frontend/selection/SelectionScopesManager.js +85 -85
  119. package/lib/esm/presentation-frontend/selection/SelectionScopesManager.js.map +1 -1
  120. package/lib/esm/presentation-frontend.d.ts +34 -34
  121. package/lib/esm/presentation-frontend.js +38 -38
  122. package/lib/esm/presentation-frontend.js.map +1 -1
  123. package/package.json +14 -14
@@ -1,130 +1,130 @@
1
- "use strict";
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
- *--------------------------------------------------------------------------------------------*/
6
- /** @packageDocumentation
7
- * @module Core
8
- */
9
- Object.defineProperty(exports, "__esModule", { value: true });
10
- exports.StateTracker = void 0;
11
- const core_bentley_1 = require("@itwin/core-bentley");
12
- /**
13
- * The tracker stores up-to-date UI state of the hierarchies on the frontend and reports
14
- * just the state changes to the backend as soon as component sends in a new hierarchy state.
15
- *
16
- * @internal
17
- */
18
- class StateTracker {
19
- constructor(ipcRequestsHandler) {
20
- this._ipcRequestsHandler = ipcRequestsHandler;
21
- this._hierarchyStates = new Map();
22
- }
23
- async updateHierarchyStateIfNeeded(imodelKey, rulesetId, stateChanges) {
24
- if (stateChanges.length === 0)
25
- return;
26
- await this._ipcRequestsHandler.updateHierarchyState({ imodelKey, rulesetId, stateChanges });
27
- }
28
- async onHierarchyClosed(imodel, rulesetId, sourceId) {
29
- const hierarchyState = this._hierarchyStates.get(rulesetId);
30
- if (!hierarchyState)
31
- return;
32
- const stateChanges = [];
33
- hierarchyState.forEach((entry) => {
34
- if (!entry.states.has(sourceId)) {
35
- // the node has no state for this source - nothing to do
36
- return;
37
- }
38
- (0, core_bentley_1.using)(new MergedNodeStateChangeReporter(entry, stateChanges), (_) => {
39
- entry.states.delete(sourceId);
40
- });
41
- });
42
- await this.updateHierarchyStateIfNeeded(imodel.key, rulesetId, stateChanges);
43
- }
44
- async onHierarchyStateChanged(imodel, rulesetId, sourceId, newHierarchyState) {
45
- let hierarchyState = this._hierarchyStates.get(rulesetId);
46
- if (!hierarchyState) {
47
- if (newHierarchyState.length === 0)
48
- return;
49
- hierarchyState = new Map();
50
- this._hierarchyStates.set(rulesetId, hierarchyState);
51
- }
52
- const handledNodeIds = new Set();
53
- const stateChanges = [];
54
- // step 1: walk over new state and report all changes
55
- newHierarchyState.forEach(({ node, state }) => {
56
- const nodeId = node === null || node === void 0 ? void 0 : node.id;
57
- const nodeKey = node === null || node === void 0 ? void 0 : node.key;
58
- const existingNodeEntry = hierarchyState.get(nodeId);
59
- if (existingNodeEntry) {
60
- (0, core_bentley_1.using)(new MergedNodeStateChangeReporter(existingNodeEntry, stateChanges), (_) => {
61
- existingNodeEntry.states.set(sourceId, state);
62
- });
63
- }
64
- else {
65
- hierarchyState.set(nodeId, { key: nodeKey, states: new Map([[sourceId, state]]) });
66
- stateChanges.push({ ...calculateMergedNodeState([state].values()), nodeKey });
67
- }
68
- handledNodeIds.add(nodeId);
69
- });
70
- // step 2: walk over old state and remove all state that's not in the new state
71
- const erasedNodeIds = new Set();
72
- hierarchyState.forEach((entry, nodeId) => {
73
- if (handledNodeIds.has(nodeId)) {
74
- // the node was handled with the new state - nothing to do here
75
- return;
76
- }
77
- if (!entry.states.has(sourceId)) {
78
- // the node had no state for this source, so it's not affected by this report
79
- return;
80
- }
81
- (0, core_bentley_1.using)(new MergedNodeStateChangeReporter(entry, stateChanges), (_) => {
82
- entry.states.delete(sourceId);
83
- });
84
- // istanbul ignore next
85
- if (entry.states.size === 0) {
86
- // there are no more components holding state for this node
87
- erasedNodeIds.add(nodeId);
88
- }
89
- });
90
- // step 3: cleanup erased node ids and possibly the whole hierarchy state
91
- for (const nodeId of erasedNodeIds) {
92
- hierarchyState.delete(nodeId);
93
- }
94
- if (hierarchyState.size === 0)
95
- this._hierarchyStates.delete(rulesetId);
96
- // finally, report
97
- await this.updateHierarchyStateIfNeeded(imodel.key, rulesetId, stateChanges);
98
- }
99
- }
100
- exports.StateTracker = StateTracker;
101
- function calculateMergedNodeState(perComponentStates) {
102
- const merged = {};
103
- for (const state of perComponentStates) {
104
- if (state.isExpanded)
105
- merged.isExpanded = true;
106
- if (state.instanceFilter) {
107
- if (!merged.instanceFilters)
108
- merged.instanceFilters = [state.instanceFilter];
109
- else if (!merged.instanceFilters.includes(state.instanceFilter))
110
- merged.instanceFilters.push(state.instanceFilter);
111
- }
112
- }
113
- return merged;
114
- }
115
- class MergedNodeStateChangeReporter {
116
- constructor(entry, outStateChanges) {
117
- this._entry = entry;
118
- this._stateBefore = calculateMergedNodeState(this._entry.states.values());
119
- this._outStateChanges = outStateChanges;
120
- }
121
- dispose() {
122
- var _a, _b, _c, _d;
123
- const stateAfter = calculateMergedNodeState(this._entry.states.values());
124
- const expandedFlagsDiffer = !!stateAfter.isExpanded !== !!this._stateBefore.isExpanded;
125
- const instanceFiltersDiffer = ((_b = (_a = stateAfter.instanceFilters) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0) !== ((_d = (_c = this._stateBefore.instanceFilters) === null || _c === void 0 ? void 0 : _c.length) !== null && _d !== void 0 ? _d : 0);
126
- if (expandedFlagsDiffer || instanceFiltersDiffer)
127
- this._outStateChanges.push({ ...stateAfter, nodeKey: this._entry.key });
128
- }
129
- }
1
+ "use strict";
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
+ *--------------------------------------------------------------------------------------------*/
6
+ /** @packageDocumentation
7
+ * @module Core
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.StateTracker = void 0;
11
+ const core_bentley_1 = require("@itwin/core-bentley");
12
+ /**
13
+ * The tracker stores up-to-date UI state of the hierarchies on the frontend and reports
14
+ * just the state changes to the backend as soon as component sends in a new hierarchy state.
15
+ *
16
+ * @internal
17
+ */
18
+ class StateTracker {
19
+ constructor(ipcRequestsHandler) {
20
+ this._ipcRequestsHandler = ipcRequestsHandler;
21
+ this._hierarchyStates = new Map();
22
+ }
23
+ async updateHierarchyStateIfNeeded(imodelKey, rulesetId, stateChanges) {
24
+ if (stateChanges.length === 0)
25
+ return;
26
+ await this._ipcRequestsHandler.updateHierarchyState({ imodelKey, rulesetId, stateChanges });
27
+ }
28
+ async onHierarchyClosed(imodel, rulesetId, sourceId) {
29
+ const hierarchyState = this._hierarchyStates.get(rulesetId);
30
+ if (!hierarchyState)
31
+ return;
32
+ const stateChanges = [];
33
+ hierarchyState.forEach((entry) => {
34
+ if (!entry.states.has(sourceId)) {
35
+ // the node has no state for this source - nothing to do
36
+ return;
37
+ }
38
+ (0, core_bentley_1.using)(new MergedNodeStateChangeReporter(entry, stateChanges), (_) => {
39
+ entry.states.delete(sourceId);
40
+ });
41
+ });
42
+ await this.updateHierarchyStateIfNeeded(imodel.key, rulesetId, stateChanges);
43
+ }
44
+ async onHierarchyStateChanged(imodel, rulesetId, sourceId, newHierarchyState) {
45
+ let hierarchyState = this._hierarchyStates.get(rulesetId);
46
+ if (!hierarchyState) {
47
+ if (newHierarchyState.length === 0)
48
+ return;
49
+ hierarchyState = new Map();
50
+ this._hierarchyStates.set(rulesetId, hierarchyState);
51
+ }
52
+ const handledNodeIds = new Set();
53
+ const stateChanges = [];
54
+ // step 1: walk over new state and report all changes
55
+ newHierarchyState.forEach(({ node, state }) => {
56
+ const nodeId = node === null || node === void 0 ? void 0 : node.id;
57
+ const nodeKey = node === null || node === void 0 ? void 0 : node.key;
58
+ const existingNodeEntry = hierarchyState.get(nodeId);
59
+ if (existingNodeEntry) {
60
+ (0, core_bentley_1.using)(new MergedNodeStateChangeReporter(existingNodeEntry, stateChanges), (_) => {
61
+ existingNodeEntry.states.set(sourceId, state);
62
+ });
63
+ }
64
+ else {
65
+ hierarchyState.set(nodeId, { key: nodeKey, states: new Map([[sourceId, state]]) });
66
+ stateChanges.push({ ...calculateMergedNodeState([state].values()), nodeKey });
67
+ }
68
+ handledNodeIds.add(nodeId);
69
+ });
70
+ // step 2: walk over old state and remove all state that's not in the new state
71
+ const erasedNodeIds = new Set();
72
+ hierarchyState.forEach((entry, nodeId) => {
73
+ if (handledNodeIds.has(nodeId)) {
74
+ // the node was handled with the new state - nothing to do here
75
+ return;
76
+ }
77
+ if (!entry.states.has(sourceId)) {
78
+ // the node had no state for this source, so it's not affected by this report
79
+ return;
80
+ }
81
+ (0, core_bentley_1.using)(new MergedNodeStateChangeReporter(entry, stateChanges), (_) => {
82
+ entry.states.delete(sourceId);
83
+ });
84
+ // istanbul ignore next
85
+ if (entry.states.size === 0) {
86
+ // there are no more components holding state for this node
87
+ erasedNodeIds.add(nodeId);
88
+ }
89
+ });
90
+ // step 3: cleanup erased node ids and possibly the whole hierarchy state
91
+ for (const nodeId of erasedNodeIds) {
92
+ hierarchyState.delete(nodeId);
93
+ }
94
+ if (hierarchyState.size === 0)
95
+ this._hierarchyStates.delete(rulesetId);
96
+ // finally, report
97
+ await this.updateHierarchyStateIfNeeded(imodel.key, rulesetId, stateChanges);
98
+ }
99
+ }
100
+ exports.StateTracker = StateTracker;
101
+ function calculateMergedNodeState(perComponentStates) {
102
+ const merged = {};
103
+ for (const state of perComponentStates) {
104
+ if (state.isExpanded)
105
+ merged.isExpanded = true;
106
+ if (state.instanceFilter) {
107
+ if (!merged.instanceFilters)
108
+ merged.instanceFilters = [state.instanceFilter];
109
+ else if (!merged.instanceFilters.includes(state.instanceFilter))
110
+ merged.instanceFilters.push(state.instanceFilter);
111
+ }
112
+ }
113
+ return merged;
114
+ }
115
+ class MergedNodeStateChangeReporter {
116
+ constructor(entry, outStateChanges) {
117
+ this._entry = entry;
118
+ this._stateBefore = calculateMergedNodeState(this._entry.states.values());
119
+ this._outStateChanges = outStateChanges;
120
+ }
121
+ dispose() {
122
+ var _a, _b, _c, _d;
123
+ const stateAfter = calculateMergedNodeState(this._entry.states.values());
124
+ const expandedFlagsDiffer = !!stateAfter.isExpanded !== !!this._stateBefore.isExpanded;
125
+ const instanceFiltersDiffer = ((_b = (_a = stateAfter.instanceFilters) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0) !== ((_d = (_c = this._stateBefore.instanceFilters) === null || _c === void 0 ? void 0 : _c.length) !== null && _d !== void 0 ? _d : 0);
126
+ if (expandedFlagsDiffer || instanceFiltersDiffer)
127
+ this._outStateChanges.push({ ...stateAfter, nodeKey: this._entry.key });
128
+ }
129
+ }
130
130
  //# sourceMappingURL=StateTracker.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"StateTracker.js","sourceRoot":"","sources":["../../../src/presentation-frontend/StateTracker.ts"],"names":[],"mappings":"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","sourcesContent":["/*---------------------------------------------------------------------------------------------\r\n* Copyright (c) Bentley Systems, Incorporated. All rights reserved.\r\n* See LICENSE.md in the project root for license terms and full copyright notice.\r\n*--------------------------------------------------------------------------------------------*/\r\n/** @packageDocumentation\r\n * @module Core\r\n */\r\n\r\nimport { IDisposable, using } from \"@itwin/core-bentley\";\r\nimport { IModelConnection } from \"@itwin/core-frontend\";\r\nimport { NodeKey } from \"@itwin/presentation-common\";\r\nimport { IpcRequestsHandler } from \"./IpcRequestsHandler\";\r\n\r\n/**\r\n * Data structure that describes information used by [[StateTracker]] to identify node.\r\n * @internal\r\n */\r\nexport interface NodeIdentifier {\r\n id: string;\r\n key: NodeKey;\r\n}\r\n\r\n/**\r\n * @internal\r\n */\r\nexport interface NodeState {\r\n isExpanded?: boolean;\r\n instanceFilter?: string;\r\n}\r\n\r\ninterface MergedNodeState {\r\n isExpanded?: boolean;\r\n instanceFilters?: string[];\r\n}\r\n\r\ninterface ReportedNodeState extends MergedNodeState {\r\n nodeKey: NodeKey | undefined;\r\n}\r\n\r\ninterface NodeStatesEntry {\r\n key: NodeKey | undefined;\r\n states: Map<string, NodeState>; // per-component node state\r\n}\r\n\r\n/**\r\n * The tracker stores up-to-date UI state of the hierarchies on the frontend and reports\r\n * just the state changes to the backend as soon as component sends in a new hierarchy state.\r\n *\r\n * @internal\r\n */\r\nexport class StateTracker {\r\n // Ruleset ID => Node ID => Node state info\r\n private _hierarchyStates: Map<string, Map<string | undefined, NodeStatesEntry>>;\r\n private _ipcRequestsHandler: IpcRequestsHandler;\r\n\r\n constructor(ipcRequestsHandler: IpcRequestsHandler) {\r\n this._ipcRequestsHandler = ipcRequestsHandler;\r\n this._hierarchyStates = new Map();\r\n }\r\n\r\n private async updateHierarchyStateIfNeeded(imodelKey: string, rulesetId: string, stateChanges: ReportedNodeState[]) {\r\n if (stateChanges.length === 0)\r\n return;\r\n await this._ipcRequestsHandler.updateHierarchyState({ imodelKey, rulesetId, stateChanges });\r\n }\r\n\r\n public async onHierarchyClosed(imodel: IModelConnection, rulesetId: string, sourceId: string) {\r\n const hierarchyState = this._hierarchyStates.get(rulesetId);\r\n if (!hierarchyState)\r\n return;\r\n\r\n const stateChanges: ReportedNodeState[] = [];\r\n hierarchyState.forEach((entry) => {\r\n if (!entry.states.has(sourceId)) {\r\n // the node has no state for this source - nothing to do\r\n return;\r\n }\r\n using(new MergedNodeStateChangeReporter(entry, stateChanges), (_) => {\r\n entry.states.delete(sourceId);\r\n });\r\n });\r\n\r\n await this.updateHierarchyStateIfNeeded(imodel.key, rulesetId, stateChanges);\r\n }\r\n\r\n public async onHierarchyStateChanged(imodel: IModelConnection, rulesetId: string, sourceId: string, newHierarchyState: Array<{ node: NodeIdentifier | undefined, state: NodeState }>) {\r\n let hierarchyState = this._hierarchyStates.get(rulesetId);\r\n if (!hierarchyState) {\r\n if (newHierarchyState.length === 0)\r\n return;\r\n\r\n hierarchyState = new Map();\r\n this._hierarchyStates.set(rulesetId, hierarchyState);\r\n }\r\n\r\n const handledNodeIds = new Set<string | undefined>();\r\n const stateChanges: ReportedNodeState[] = [];\r\n\r\n // step 1: walk over new state and report all changes\r\n newHierarchyState.forEach(({ node, state }) => {\r\n const nodeId = node?.id;\r\n const nodeKey = node?.key;\r\n const existingNodeEntry = hierarchyState!.get(nodeId);\r\n if (existingNodeEntry) {\r\n using(new MergedNodeStateChangeReporter(existingNodeEntry, stateChanges), (_) => {\r\n existingNodeEntry.states.set(sourceId, state);\r\n });\r\n } else {\r\n hierarchyState!.set(nodeId, { key: nodeKey, states: new Map([[sourceId, state]]) });\r\n stateChanges.push({ ...calculateMergedNodeState([state].values()), nodeKey });\r\n }\r\n handledNodeIds.add(nodeId);\r\n });\r\n\r\n // step 2: walk over old state and remove all state that's not in the new state\r\n const erasedNodeIds = new Set<string | undefined>();\r\n hierarchyState.forEach((entry, nodeId) => {\r\n if (handledNodeIds.has(nodeId)) {\r\n // the node was handled with the new state - nothing to do here\r\n return;\r\n }\r\n\r\n if (!entry.states.has(sourceId)) {\r\n // the node had no state for this source, so it's not affected by this report\r\n return;\r\n }\r\n\r\n using(new MergedNodeStateChangeReporter(entry, stateChanges), (_) => {\r\n entry.states.delete(sourceId);\r\n });\r\n\r\n // istanbul ignore next\r\n if (entry.states.size === 0) {\r\n // there are no more components holding state for this node\r\n erasedNodeIds.add(nodeId);\r\n }\r\n });\r\n\r\n // step 3: cleanup erased node ids and possibly the whole hierarchy state\r\n for (const nodeId of erasedNodeIds) {\r\n hierarchyState.delete(nodeId);\r\n }\r\n if (hierarchyState.size === 0)\r\n this._hierarchyStates.delete(rulesetId);\r\n\r\n // finally, report\r\n await this.updateHierarchyStateIfNeeded(imodel.key, rulesetId, stateChanges);\r\n }\r\n}\r\n\r\nfunction calculateMergedNodeState(perComponentStates: IterableIterator<NodeState>): MergedNodeState {\r\n const merged: MergedNodeState = {};\r\n for (const state of perComponentStates) {\r\n if (state.isExpanded)\r\n merged.isExpanded = true;\r\n if (state.instanceFilter) {\r\n if (!merged.instanceFilters)\r\n merged.instanceFilters = [state.instanceFilter];\r\n else if (!merged.instanceFilters.includes(state.instanceFilter))\r\n merged.instanceFilters.push(state.instanceFilter);\r\n }\r\n }\r\n return merged;\r\n}\r\n\r\nclass MergedNodeStateChangeReporter implements IDisposable {\r\n private _entry: NodeStatesEntry;\r\n private _stateBefore: MergedNodeState;\r\n private _outStateChanges: ReportedNodeState[];\r\n public constructor(entry: NodeStatesEntry, outStateChanges: ReportedNodeState[]) {\r\n this._entry = entry;\r\n this._stateBefore = calculateMergedNodeState(this._entry.states.values());\r\n this._outStateChanges = outStateChanges;\r\n }\r\n public dispose() {\r\n const stateAfter = calculateMergedNodeState(this._entry.states.values());\r\n const expandedFlagsDiffer = !!stateAfter.isExpanded !== !!this._stateBefore.isExpanded;\r\n const instanceFiltersDiffer = (stateAfter.instanceFilters?.length ?? 0) !== (this._stateBefore.instanceFilters?.length ?? 0);\r\n if (expandedFlagsDiffer || instanceFiltersDiffer)\r\n this._outStateChanges.push({ ...stateAfter, nodeKey: this._entry.key });\r\n }\r\n}\r\n"]}
1
+ {"version":3,"file":"StateTracker.js","sourceRoot":"","sources":["../../../src/presentation-frontend/StateTracker.ts"],"names":[],"mappings":";AAAA;;;+FAG+F;AAC/F;;GAEG;;;AAEH,sDAAyD;AAoCzD;;;;;GAKG;AACH,MAAa,YAAY;IAKvB,YAAY,kBAAsC;QAChD,IAAI,CAAC,mBAAmB,GAAG,kBAAkB,CAAC;QAC9C,IAAI,CAAC,gBAAgB,GAAG,IAAI,GAAG,EAAE,CAAC;IACpC,CAAC;IAEO,KAAK,CAAC,4BAA4B,CAAC,SAAiB,EAAE,SAAiB,EAAE,YAAiC;QAChH,IAAI,YAAY,CAAC,MAAM,KAAK,CAAC;YAC3B,OAAO;QACT,MAAM,IAAI,CAAC,mBAAmB,CAAC,oBAAoB,CAAC,EAAE,SAAS,EAAE,SAAS,EAAE,YAAY,EAAE,CAAC,CAAC;IAC9F,CAAC;IAEM,KAAK,CAAC,iBAAiB,CAAC,MAAwB,EAAE,SAAiB,EAAE,QAAgB;QAC1F,MAAM,cAAc,GAAG,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QAC5D,IAAI,CAAC,cAAc;YACjB,OAAO;QAET,MAAM,YAAY,GAAwB,EAAE,CAAC;QAC7C,cAAc,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,EAAE;YAC/B,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE;gBAC/B,wDAAwD;gBACxD,OAAO;aACR;YACD,IAAA,oBAAK,EAAC,IAAI,6BAA6B,CAAC,KAAK,EAAE,YAAY,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE;gBAClE,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;YAChC,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;QAEH,MAAM,IAAI,CAAC,4BAA4B,CAAC,MAAM,CAAC,GAAG,EAAE,SAAS,EAAE,YAAY,CAAC,CAAC;IAC/E,CAAC;IAEM,KAAK,CAAC,uBAAuB,CAAC,MAAwB,EAAE,SAAiB,EAAE,QAAgB,EAAE,iBAAgF;QAClL,IAAI,cAAc,GAAG,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QAC1D,IAAI,CAAC,cAAc,EAAE;YACnB,IAAI,iBAAiB,CAAC,MAAM,KAAK,CAAC;gBAChC,OAAO;YAET,cAAc,GAAG,IAAI,GAAG,EAAE,CAAC;YAC3B,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,SAAS,EAAE,cAAc,CAAC,CAAC;SACtD;QAED,MAAM,cAAc,GAAG,IAAI,GAAG,EAAsB,CAAC;QACrD,MAAM,YAAY,GAAwB,EAAE,CAAC;QAE7C,qDAAqD;QACrD,iBAAiB,CAAC,OAAO,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,EAAE;YAC5C,MAAM,MAAM,GAAG,IAAI,aAAJ,IAAI,uBAAJ,IAAI,CAAE,EAAE,CAAC;YACxB,MAAM,OAAO,GAAG,IAAI,aAAJ,IAAI,uBAAJ,IAAI,CAAE,GAAG,CAAC;YAC1B,MAAM,iBAAiB,GAAG,cAAe,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;YACtD,IAAI,iBAAiB,EAAE;gBACrB,IAAA,oBAAK,EAAC,IAAI,6BAA6B,CAAC,iBAAiB,EAAE,YAAY,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE;oBAC9E,iBAAiB,CAAC,MAAM,CAAC,GAAG,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;gBAChD,CAAC,CAAC,CAAC;aACJ;iBAAM;gBACL,cAAe,CAAC,GAAG,CAAC,MAAM,EAAE,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,GAAG,CAAC,CAAC,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;gBACpF,YAAY,CAAC,IAAI,CAAC,EAAE,GAAG,wBAAwB,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC;aAC/E;YACD,cAAc,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QAC7B,CAAC,CAAC,CAAC;QAEH,+EAA+E;QAC/E,MAAM,aAAa,GAAG,IAAI,GAAG,EAAsB,CAAC;QACpD,cAAc,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE;YACvC,IAAI,cAAc,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE;gBAC9B,+DAA+D;gBAC/D,OAAO;aACR;YAED,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE;gBAC/B,6EAA6E;gBAC7E,OAAO;aACR;YAED,IAAA,oBAAK,EAAC,IAAI,6BAA6B,CAAC,KAAK,EAAE,YAAY,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE;gBAClE,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;YAChC,CAAC,CAAC,CAAC;YAEH,uBAAuB;YACvB,IAAI,KAAK,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,EAAE;gBAC3B,2DAA2D;gBAC3D,aAAa,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;aAC3B;QACH,CAAC,CAAC,CAAC;QAEH,yEAAyE;QACzE,KAAK,MAAM,MAAM,IAAI,aAAa,EAAE;YAClC,cAAc,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;SAC/B;QACD,IAAI,cAAc,CAAC,IAAI,KAAK,CAAC;YAC3B,IAAI,CAAC,gBAAgB,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;QAE1C,kBAAkB;QAClB,MAAM,IAAI,CAAC,4BAA4B,CAAC,MAAM,CAAC,GAAG,EAAE,SAAS,EAAE,YAAY,CAAC,CAAC;IAC/E,CAAC;CACF;AAlGD,oCAkGC;AAED,SAAS,wBAAwB,CAAC,kBAA+C;IAC/E,MAAM,MAAM,GAAoB,EAAE,CAAC;IACnC,KAAK,MAAM,KAAK,IAAI,kBAAkB,EAAE;QACtC,IAAI,KAAK,CAAC,UAAU;YAClB,MAAM,CAAC,UAAU,GAAG,IAAI,CAAC;QAC3B,IAAI,KAAK,CAAC,cAAc,EAAE;YACxB,IAAI,CAAC,MAAM,CAAC,eAAe;gBACzB,MAAM,CAAC,eAAe,GAAG,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC;iBAC7C,IAAI,CAAC,MAAM,CAAC,eAAe,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC;gBAC7D,MAAM,CAAC,eAAe,CAAC,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC;SACrD;KACF;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,6BAA6B;IAIjC,YAAmB,KAAsB,EAAE,eAAoC;QAC7E,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC;QACpB,IAAI,CAAC,YAAY,GAAG,wBAAwB,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC;QAC1E,IAAI,CAAC,gBAAgB,GAAG,eAAe,CAAC;IAC1C,CAAC;IACM,OAAO;;QACZ,MAAM,UAAU,GAAG,wBAAwB,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC;QACzE,MAAM,mBAAmB,GAAG,CAAC,CAAC,UAAU,CAAC,UAAU,KAAK,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,UAAU,CAAC;QACvF,MAAM,qBAAqB,GAAG,CAAC,MAAA,MAAA,UAAU,CAAC,eAAe,0CAAE,MAAM,mCAAI,CAAC,CAAC,KAAK,CAAC,MAAA,MAAA,IAAI,CAAC,YAAY,CAAC,eAAe,0CAAE,MAAM,mCAAI,CAAC,CAAC,CAAC;QAC7H,IAAI,mBAAmB,IAAI,qBAAqB;YAC9C,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,EAAE,GAAG,UAAU,EAAE,OAAO,EAAE,IAAI,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC;IAC5E,CAAC;CACF","sourcesContent":["/*---------------------------------------------------------------------------------------------\n* Copyright (c) Bentley Systems, Incorporated. All rights reserved.\n* See LICENSE.md in the project root for license terms and full copyright notice.\n*--------------------------------------------------------------------------------------------*/\n/** @packageDocumentation\n * @module Core\n */\n\nimport { IDisposable, using } from \"@itwin/core-bentley\";\nimport { IModelConnection } from \"@itwin/core-frontend\";\nimport { NodeKey } from \"@itwin/presentation-common\";\nimport { IpcRequestsHandler } from \"./IpcRequestsHandler\";\n\n/**\n * Data structure that describes information used by [[StateTracker]] to identify node.\n * @internal\n */\nexport interface NodeIdentifier {\n id: string;\n key: NodeKey;\n}\n\n/**\n * @internal\n */\nexport interface NodeState {\n isExpanded?: boolean;\n instanceFilter?: string;\n}\n\ninterface MergedNodeState {\n isExpanded?: boolean;\n instanceFilters?: string[];\n}\n\ninterface ReportedNodeState extends MergedNodeState {\n nodeKey: NodeKey | undefined;\n}\n\ninterface NodeStatesEntry {\n key: NodeKey | undefined;\n states: Map<string, NodeState>; // per-component node state\n}\n\n/**\n * The tracker stores up-to-date UI state of the hierarchies on the frontend and reports\n * just the state changes to the backend as soon as component sends in a new hierarchy state.\n *\n * @internal\n */\nexport class StateTracker {\n // Ruleset ID => Node ID => Node state info\n private _hierarchyStates: Map<string, Map<string | undefined, NodeStatesEntry>>;\n private _ipcRequestsHandler: IpcRequestsHandler;\n\n constructor(ipcRequestsHandler: IpcRequestsHandler) {\n this._ipcRequestsHandler = ipcRequestsHandler;\n this._hierarchyStates = new Map();\n }\n\n private async updateHierarchyStateIfNeeded(imodelKey: string, rulesetId: string, stateChanges: ReportedNodeState[]) {\n if (stateChanges.length === 0)\n return;\n await this._ipcRequestsHandler.updateHierarchyState({ imodelKey, rulesetId, stateChanges });\n }\n\n public async onHierarchyClosed(imodel: IModelConnection, rulesetId: string, sourceId: string) {\n const hierarchyState = this._hierarchyStates.get(rulesetId);\n if (!hierarchyState)\n return;\n\n const stateChanges: ReportedNodeState[] = [];\n hierarchyState.forEach((entry) => {\n if (!entry.states.has(sourceId)) {\n // the node has no state for this source - nothing to do\n return;\n }\n using(new MergedNodeStateChangeReporter(entry, stateChanges), (_) => {\n entry.states.delete(sourceId);\n });\n });\n\n await this.updateHierarchyStateIfNeeded(imodel.key, rulesetId, stateChanges);\n }\n\n public async onHierarchyStateChanged(imodel: IModelConnection, rulesetId: string, sourceId: string, newHierarchyState: Array<{ node: NodeIdentifier | undefined, state: NodeState }>) {\n let hierarchyState = this._hierarchyStates.get(rulesetId);\n if (!hierarchyState) {\n if (newHierarchyState.length === 0)\n return;\n\n hierarchyState = new Map();\n this._hierarchyStates.set(rulesetId, hierarchyState);\n }\n\n const handledNodeIds = new Set<string | undefined>();\n const stateChanges: ReportedNodeState[] = [];\n\n // step 1: walk over new state and report all changes\n newHierarchyState.forEach(({ node, state }) => {\n const nodeId = node?.id;\n const nodeKey = node?.key;\n const existingNodeEntry = hierarchyState!.get(nodeId);\n if (existingNodeEntry) {\n using(new MergedNodeStateChangeReporter(existingNodeEntry, stateChanges), (_) => {\n existingNodeEntry.states.set(sourceId, state);\n });\n } else {\n hierarchyState!.set(nodeId, { key: nodeKey, states: new Map([[sourceId, state]]) });\n stateChanges.push({ ...calculateMergedNodeState([state].values()), nodeKey });\n }\n handledNodeIds.add(nodeId);\n });\n\n // step 2: walk over old state and remove all state that's not in the new state\n const erasedNodeIds = new Set<string | undefined>();\n hierarchyState.forEach((entry, nodeId) => {\n if (handledNodeIds.has(nodeId)) {\n // the node was handled with the new state - nothing to do here\n return;\n }\n\n if (!entry.states.has(sourceId)) {\n // the node had no state for this source, so it's not affected by this report\n return;\n }\n\n using(new MergedNodeStateChangeReporter(entry, stateChanges), (_) => {\n entry.states.delete(sourceId);\n });\n\n // istanbul ignore next\n if (entry.states.size === 0) {\n // there are no more components holding state for this node\n erasedNodeIds.add(nodeId);\n }\n });\n\n // step 3: cleanup erased node ids and possibly the whole hierarchy state\n for (const nodeId of erasedNodeIds) {\n hierarchyState.delete(nodeId);\n }\n if (hierarchyState.size === 0)\n this._hierarchyStates.delete(rulesetId);\n\n // finally, report\n await this.updateHierarchyStateIfNeeded(imodel.key, rulesetId, stateChanges);\n }\n}\n\nfunction calculateMergedNodeState(perComponentStates: IterableIterator<NodeState>): MergedNodeState {\n const merged: MergedNodeState = {};\n for (const state of perComponentStates) {\n if (state.isExpanded)\n merged.isExpanded = true;\n if (state.instanceFilter) {\n if (!merged.instanceFilters)\n merged.instanceFilters = [state.instanceFilter];\n else if (!merged.instanceFilters.includes(state.instanceFilter))\n merged.instanceFilters.push(state.instanceFilter);\n }\n }\n return merged;\n}\n\nclass MergedNodeStateChangeReporter implements IDisposable {\n private _entry: NodeStatesEntry;\n private _stateBefore: MergedNodeState;\n private _outStateChanges: ReportedNodeState[];\n public constructor(entry: NodeStatesEntry, outStateChanges: ReportedNodeState[]) {\n this._entry = entry;\n this._stateBefore = calculateMergedNodeState(this._entry.states.values());\n this._outStateChanges = outStateChanges;\n }\n public dispose() {\n const stateAfter = calculateMergedNodeState(this._entry.states.values());\n const expandedFlagsDiffer = !!stateAfter.isExpanded !== !!this._stateBefore.isExpanded;\n const instanceFiltersDiffer = (stateAfter.instanceFilters?.length ?? 0) !== (this._stateBefore.instanceFilters?.length ?? 0);\n if (expandedFlagsDiffer || instanceFiltersDiffer)\n this._outStateChanges.push({ ...stateAfter, nodeKey: this._entry.key });\n }\n}\n"]}
@@ -1,133 +1,133 @@
1
- /** @packageDocumentation
2
- * @module Core
3
- */
4
- import { BeEvent, IDisposable } from "@itwin/core-bentley";
5
- import { IModelConnection } from "@itwin/core-frontend";
6
- import { Field } from "@itwin/presentation-common";
7
- import { IFavoritePropertiesStorage } from "./FavoritePropertiesStorage";
8
- /**
9
- * Scopes that favorite properties can be stored in.
10
- * @public
11
- */
12
- export declare enum FavoritePropertiesScope {
13
- Global = 0,
14
- ITwin = 1,
15
- IModel = 2
16
- }
17
- /**
18
- * Format:
19
- * Regular property - [{path from parent class}-]{schema name}:{class name}:{property name}.
20
- * Nested property - [{path from parent class}-]{content class schema name}:{content class name}.
21
- * Primitive property - {field name}.
22
- * @public
23
- */
24
- export declare type PropertyFullName = string;
25
- /**
26
- * Holds the information of favorite properties ordering.
27
- * @public
28
- */
29
- export interface FavoritePropertiesOrderInfo {
30
- parentClassName: string | undefined;
31
- name: PropertyFullName;
32
- priority: number;
33
- orderedTimestamp: Date;
34
- }
35
- /**
36
- * Properties for initializing [[FavoritePropertiesManager]]
37
- * @public
38
- */
39
- export interface FavoritePropertiesManagerProps {
40
- /**
41
- * Implementation of a persistence layer for storing favorite properties and their order.
42
- * @public
43
- */
44
- storage: IFavoritePropertiesStorage;
45
- }
46
- /**
47
- * The favorite property manager which lets to store favorite properties
48
- * and check if field contains favorite properties.
49
- *
50
- * @public
51
- */
52
- export declare class FavoritePropertiesManager implements IDisposable {
53
- /**
54
- * Used in tests to avoid collisions between multiple runs using the same storage
55
- * @internal
56
- */
57
- static FAVORITES_IDENTIFIER_PREFIX: string;
58
- /** Event raised after favorite properties have changed. */
59
- onFavoritesChanged: BeEvent<() => void>;
60
- private _storage;
61
- private _globalProperties;
62
- private _iTwinProperties;
63
- private _imodelProperties;
64
- private _imodelBaseClassesByClass;
65
- /** Property order is saved only in iModel scope */
66
- private _propertiesOrder;
67
- constructor(props: FavoritePropertiesManagerProps);
68
- dispose(): void;
69
- /**
70
- * Initialize favorite properties for the provided IModelConnection.
71
- */
72
- initializeConnection: (imodel: IModelConnection) => Promise<void>;
73
- /**
74
- * Function that removes order information of properties that are no longer
75
- * favorited and adds missing order information for favorited properties.
76
- */
77
- private _adjustPropertyOrderInfos;
78
- private validateInitialization;
79
- /**
80
- * Adds favorite properties into a certain scope.
81
- * @param field Field that contains properties. If field contains multiple properties, all of them will be favorited.
82
- * @param imodel IModelConnection.
83
- * @param scope FavoritePropertiesScope to put the favorite properties into.
84
- * @note `initializeConnection` must be called with the `imodel` before calling this function.
85
- */
86
- add(field: Field, imodel: IModelConnection, scope: FavoritePropertiesScope): Promise<void>;
87
- /**
88
- * Removes favorite properties from a scope specified and all the more general scopes.
89
- * @param field Field that contains properties. If field contains multiple properties, all of them will be un-favorited.
90
- * @param imodel IModelConnection.
91
- * @param scope FavoritePropertiesScope to remove the favorite properties from. It also removes from more general scopes.
92
- * @note `initializeConnection` must be called with the `imodel` before calling this function.
93
- */
94
- remove(field: Field, imodel: IModelConnection, scope: FavoritePropertiesScope): Promise<void>;
95
- /**
96
- * Removes all favorite properties from a certain scope.
97
- * @param imodel IModelConnection.
98
- * @param scope FavoritePropertiesScope to remove the favorite properties from.
99
- * @note `initializeConnection` must be called with the `imodel` before calling this function.
100
- */
101
- clear(imodel: IModelConnection, scope: FavoritePropertiesScope): Promise<void>;
102
- /**
103
- * Check if field contains at least one favorite property.
104
- * @param field Field that contains properties.
105
- * @param imodel IModelConnection.
106
- * @param scope FavoritePropertiesScope to check for favorite properties. It also checks the more general scopes.
107
- * @note `initializeConnection` must be called with the `imodel` before calling this function.
108
- */
109
- has(field: Field, imodel: IModelConnection, scope: FavoritePropertiesScope): boolean;
110
- /**
111
- * Sorts an array of fields with respect to favorite property order.
112
- * Non-favorited fields get sorted by their default priority and always have lower priority than favorited fields.
113
- * @param imodel IModelConnection.
114
- * @param fields Array of Field's that needs to be sorted.
115
- * @note `initializeConnection` must be called with the `imodel` before calling this function.
116
- */
117
- sortFields: (imodel: IModelConnection, fields: Field[]) => Field[];
118
- private getFieldPriority;
119
- private _getBaseClassesByClass;
120
- /** Changes field properties priorities to lower than another fields priority
121
- * @param imodel IModelConnection.
122
- * @param field Field that priority is being changed.
123
- * @param afterField Field that goes before the moved field. If undefined the moving field is changed to the highest priority (to the top).
124
- * @param visibleFields Array of fields to move the field in.
125
- * @note `initializeConnection` must be called with the `imodel` before calling this function.
126
- */
127
- changeFieldPriority(imodel: IModelConnection, field: Field, afterField: Field | undefined, visibleFields: Field[]): Promise<void>;
128
- }
129
- /** @internal */
130
- export declare const getFieldInfos: (field: Field) => Set<PropertyFullName>;
131
- /** @internal */
132
- export declare const createFieldOrderInfos: (field: Field) => FavoritePropertiesOrderInfo[];
1
+ /** @packageDocumentation
2
+ * @module Core
3
+ */
4
+ import { BeEvent, IDisposable } from "@itwin/core-bentley";
5
+ import { IModelConnection } from "@itwin/core-frontend";
6
+ import { Field } from "@itwin/presentation-common";
7
+ import { IFavoritePropertiesStorage } from "./FavoritePropertiesStorage";
8
+ /**
9
+ * Scopes that favorite properties can be stored in.
10
+ * @public
11
+ */
12
+ export declare enum FavoritePropertiesScope {
13
+ Global = 0,
14
+ ITwin = 1,
15
+ IModel = 2
16
+ }
17
+ /**
18
+ * Format:
19
+ * Regular property - [{path from parent class}-]{schema name}:{class name}:{property name}.
20
+ * Nested property - [{path from parent class}-]{content class schema name}:{content class name}.
21
+ * Primitive property - {field name}.
22
+ * @public
23
+ */
24
+ export declare type PropertyFullName = string;
25
+ /**
26
+ * Holds the information of favorite properties ordering.
27
+ * @public
28
+ */
29
+ export interface FavoritePropertiesOrderInfo {
30
+ parentClassName: string | undefined;
31
+ name: PropertyFullName;
32
+ priority: number;
33
+ orderedTimestamp: Date;
34
+ }
35
+ /**
36
+ * Properties for initializing [[FavoritePropertiesManager]]
37
+ * @public
38
+ */
39
+ export interface FavoritePropertiesManagerProps {
40
+ /**
41
+ * Implementation of a persistence layer for storing favorite properties and their order.
42
+ * @public
43
+ */
44
+ storage: IFavoritePropertiesStorage;
45
+ }
46
+ /**
47
+ * The favorite property manager which lets to store favorite properties
48
+ * and check if field contains favorite properties.
49
+ *
50
+ * @public
51
+ */
52
+ export declare class FavoritePropertiesManager implements IDisposable {
53
+ /**
54
+ * Used in tests to avoid collisions between multiple runs using the same storage
55
+ * @internal
56
+ */
57
+ static FAVORITES_IDENTIFIER_PREFIX: string;
58
+ /** Event raised after favorite properties have changed. */
59
+ onFavoritesChanged: BeEvent<() => void>;
60
+ private _storage;
61
+ private _globalProperties;
62
+ private _iTwinProperties;
63
+ private _imodelProperties;
64
+ private _imodelBaseClassesByClass;
65
+ /** Property order is saved only in iModel scope */
66
+ private _propertiesOrder;
67
+ constructor(props: FavoritePropertiesManagerProps);
68
+ dispose(): void;
69
+ /**
70
+ * Initialize favorite properties for the provided IModelConnection.
71
+ */
72
+ initializeConnection: (imodel: IModelConnection) => Promise<void>;
73
+ /**
74
+ * Function that removes order information of properties that are no longer
75
+ * favorited and adds missing order information for favorited properties.
76
+ */
77
+ private _adjustPropertyOrderInfos;
78
+ private validateInitialization;
79
+ /**
80
+ * Adds favorite properties into a certain scope.
81
+ * @param field Field that contains properties. If field contains multiple properties, all of them will be favorited.
82
+ * @param imodel IModelConnection.
83
+ * @param scope FavoritePropertiesScope to put the favorite properties into.
84
+ * @note `initializeConnection` must be called with the `imodel` before calling this function.
85
+ */
86
+ add(field: Field, imodel: IModelConnection, scope: FavoritePropertiesScope): Promise<void>;
87
+ /**
88
+ * Removes favorite properties from a scope specified and all the more general scopes.
89
+ * @param field Field that contains properties. If field contains multiple properties, all of them will be un-favorited.
90
+ * @param imodel IModelConnection.
91
+ * @param scope FavoritePropertiesScope to remove the favorite properties from. It also removes from more general scopes.
92
+ * @note `initializeConnection` must be called with the `imodel` before calling this function.
93
+ */
94
+ remove(field: Field, imodel: IModelConnection, scope: FavoritePropertiesScope): Promise<void>;
95
+ /**
96
+ * Removes all favorite properties from a certain scope.
97
+ * @param imodel IModelConnection.
98
+ * @param scope FavoritePropertiesScope to remove the favorite properties from.
99
+ * @note `initializeConnection` must be called with the `imodel` before calling this function.
100
+ */
101
+ clear(imodel: IModelConnection, scope: FavoritePropertiesScope): Promise<void>;
102
+ /**
103
+ * Check if field contains at least one favorite property.
104
+ * @param field Field that contains properties.
105
+ * @param imodel IModelConnection.
106
+ * @param scope FavoritePropertiesScope to check for favorite properties. It also checks the more general scopes.
107
+ * @note `initializeConnection` must be called with the `imodel` before calling this function.
108
+ */
109
+ has(field: Field, imodel: IModelConnection, scope: FavoritePropertiesScope): boolean;
110
+ /**
111
+ * Sorts an array of fields with respect to favorite property order.
112
+ * Non-favorited fields get sorted by their default priority and always have lower priority than favorited fields.
113
+ * @param imodel IModelConnection.
114
+ * @param fields Array of Field's that needs to be sorted.
115
+ * @note `initializeConnection` must be called with the `imodel` before calling this function.
116
+ */
117
+ sortFields: (imodel: IModelConnection, fields: Field[]) => Field[];
118
+ private getFieldPriority;
119
+ private _getBaseClassesByClass;
120
+ /** Changes field properties priorities to lower than another fields priority
121
+ * @param imodel IModelConnection.
122
+ * @param field Field that priority is being changed.
123
+ * @param afterField Field that goes before the moved field. If undefined the moving field is changed to the highest priority (to the top).
124
+ * @param visibleFields Array of fields to move the field in.
125
+ * @note `initializeConnection` must be called with the `imodel` before calling this function.
126
+ */
127
+ changeFieldPriority(imodel: IModelConnection, field: Field, afterField: Field | undefined, visibleFields: Field[]): Promise<void>;
128
+ }
129
+ /** @internal */
130
+ export declare const getFieldInfos: (field: Field) => Set<PropertyFullName>;
131
+ /** @internal */
132
+ export declare const createFieldOrderInfos: (field: Field) => FavoritePropertiesOrderInfo[];
133
133
  //# sourceMappingURL=FavoritePropertiesManager.d.ts.map