angular-slickgrid 3.3.2 → 4.1.2

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 (55) hide show
  1. package/README.md +180 -188
  2. package/angular-slickgrid.d.ts +1 -3
  3. package/app/modules/angular-slickgrid/components/angular-slickgrid.component.d.ts +9 -6
  4. package/app/modules/angular-slickgrid/extensions/index.d.ts +1 -1
  5. package/app/modules/angular-slickgrid/extensions/{rowDetailViewExtension.d.ts → slickRowDetailView.d.ts} +40 -27
  6. package/app/modules/angular-slickgrid/index.d.ts +1 -1
  7. package/app/modules/angular-slickgrid/models/angularGridInstance.interface.d.ts +1 -1
  8. package/app/modules/angular-slickgrid/modules/angular-slickgrid.module.d.ts +7 -0
  9. package/app/modules/angular-slickgrid/services/angularUtil.service.d.ts +3 -0
  10. package/app/modules/angular-slickgrid/services/bsDropdown.service.d.ts +3 -0
  11. package/app/modules/angular-slickgrid/services/container.service.d.ts +3 -0
  12. package/app/modules/angular-slickgrid/services/translater.service.d.ts +3 -0
  13. package/docs/assets/lib/multiple-select/README.md +17 -0
  14. package/esm2020/angular-slickgrid.mjs +5 -0
  15. package/esm2020/app/modules/angular-slickgrid/components/angular-slickgrid.component.mjs +1168 -0
  16. package/{esm2015/app/modules/angular-slickgrid/constants.js → esm2020/app/modules/angular-slickgrid/constants.mjs} +0 -0
  17. package/{esm2015/app/modules/angular-slickgrid/extensions/index.js → esm2020/app/modules/angular-slickgrid/extensions/index.mjs} +2 -2
  18. package/esm2020/app/modules/angular-slickgrid/extensions/slickRowDetailView.mjs +300 -0
  19. package/esm2020/app/modules/angular-slickgrid/global-grid-options.mjs +243 -0
  20. package/{esm2015/app/modules/angular-slickgrid/index.js → esm2020/app/modules/angular-slickgrid/index.mjs} +2 -2
  21. package/{esm2015/app/modules/angular-slickgrid/models/angularComponentOutput.interface.js → esm2020/app/modules/angular-slickgrid/models/angularComponentOutput.interface.mjs} +0 -0
  22. package/esm2020/app/modules/angular-slickgrid/models/angularGridInstance.interface.mjs +2 -0
  23. package/{esm2015/app/modules/angular-slickgrid/models/externalTestingDependencies.interface.js → esm2020/app/modules/angular-slickgrid/models/externalTestingDependencies.interface.mjs} +0 -0
  24. package/{esm2015/app/modules/angular-slickgrid/models/gridOption.interface.js → esm2020/app/modules/angular-slickgrid/models/gridOption.interface.mjs} +0 -0
  25. package/{esm2015/app/modules/angular-slickgrid/models/index.js → esm2020/app/modules/angular-slickgrid/models/index.mjs} +0 -0
  26. package/{esm2015/app/modules/angular-slickgrid/models/rowDetailView.interface.js → esm2020/app/modules/angular-slickgrid/models/rowDetailView.interface.mjs} +0 -0
  27. package/{esm2015/app/modules/angular-slickgrid/models/slickGrid.interface.js → esm2020/app/modules/angular-slickgrid/models/slickGrid.interface.mjs} +0 -0
  28. package/esm2020/app/modules/angular-slickgrid/modules/angular-slickgrid.module.mjs +46 -0
  29. package/esm2020/app/modules/angular-slickgrid/services/angularUtil.service.mjs +46 -0
  30. package/esm2020/app/modules/angular-slickgrid/services/bsDropdown.service.mjs +103 -0
  31. package/esm2020/app/modules/angular-slickgrid/services/container.service.mjs +26 -0
  32. package/{esm2015/app/modules/angular-slickgrid/services/index.js → esm2020/app/modules/angular-slickgrid/services/index.mjs} +0 -0
  33. package/esm2020/app/modules/angular-slickgrid/services/translater.service.mjs +43 -0
  34. package/{esm2015/app/modules/angular-slickgrid/services/utilities.js → esm2020/app/modules/angular-slickgrid/services/utilities.mjs} +0 -0
  35. package/{esm2015/app/modules/angular-slickgrid/slickgrid-config.js → esm2020/app/modules/angular-slickgrid/slickgrid-config.mjs} +0 -0
  36. package/{esm2015/public_api.js → esm2020/public_api.mjs} +0 -0
  37. package/fesm2015/{angular-slickgrid.js → angular-slickgrid.mjs} +252 -282
  38. package/fesm2015/angular-slickgrid.mjs.map +1 -0
  39. package/fesm2020/angular-slickgrid.mjs +2066 -0
  40. package/fesm2020/angular-slickgrid.mjs.map +1 -0
  41. package/package.json +38 -23
  42. package/angular-slickgrid.metadata.json +0 -1
  43. package/bundles/angular-slickgrid.umd.js +0 -2642
  44. package/bundles/angular-slickgrid.umd.js.map +0 -1
  45. package/esm2015/angular-slickgrid.js +0 -7
  46. package/esm2015/app/modules/angular-slickgrid/components/angular-slickgrid.component.js +0 -1202
  47. package/esm2015/app/modules/angular-slickgrid/extensions/rowDetailViewExtension.js +0 -342
  48. package/esm2015/app/modules/angular-slickgrid/global-grid-options.js +0 -243
  49. package/esm2015/app/modules/angular-slickgrid/models/angularGridInstance.interface.js +0 -2
  50. package/esm2015/app/modules/angular-slickgrid/modules/angular-slickgrid.module.js +0 -37
  51. package/esm2015/app/modules/angular-slickgrid/services/angularUtil.service.js +0 -48
  52. package/esm2015/app/modules/angular-slickgrid/services/bsDropdown.service.js +0 -103
  53. package/esm2015/app/modules/angular-slickgrid/services/container.service.js +0 -24
  54. package/esm2015/app/modules/angular-slickgrid/services/translater.service.js +0 -47
  55. package/fesm2015/angular-slickgrid.js.map +0 -1
@@ -1,2 +1,2 @@
1
- export * from './rowDetailViewExtension';
2
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9zcmMvYXBwL21vZHVsZXMvYW5ndWxhci1zbGlja2dyaWQvZXh0ZW5zaW9ucy9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxjQUFjLDBCQUEwQixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiZXhwb3J0ICogZnJvbSAnLi9yb3dEZXRhaWxWaWV3RXh0ZW5zaW9uJztcclxuIl19
1
+ export * from './slickRowDetailView';
2
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9zcmMvYXBwL21vZHVsZXMvYW5ndWxhci1zbGlja2dyaWQvZXh0ZW5zaW9ucy9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxjQUFjLHNCQUFzQixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiZXhwb3J0ICogZnJvbSAnLi9zbGlja1Jvd0RldGFpbFZpZXcnO1xyXG4iXX0=
@@ -0,0 +1,300 @@
1
+ import 'slickgrid/plugins/slick.rowdetailview';
2
+ import 'slickgrid/plugins/slick.rowselectionmodel';
3
+ import { addToArrayWhenNotExists, castObservableToPromise, SlickRowSelectionModel, unsubscribeAll, } from '@slickgrid-universal/common';
4
+ import { SlickRowDetailView as UniversalSlickRowDetailView } from '@slickgrid-universal/row-detail-view-plugin';
5
+ import { Observable } from 'rxjs';
6
+ import * as DOMPurify from 'dompurify';
7
+ const ROW_DETAIL_CONTAINER_PREFIX = 'container_';
8
+ const PRELOAD_CONTAINER_PREFIX = 'container_loading';
9
+ export class SlickRowDetailView extends UniversalSlickRowDetailView {
10
+ constructor(angularUtilService, appRef, eventPubSubService, gridContainerElement, rxjs) {
11
+ super();
12
+ this.angularUtilService = angularUtilService;
13
+ this.appRef = appRef;
14
+ this.eventPubSubService = eventPubSubService;
15
+ this.gridContainerElement = gridContainerElement;
16
+ this.rxjs = rxjs;
17
+ this._views = [];
18
+ this._subscriptions = [];
19
+ }
20
+ get addonOptions() {
21
+ return this.getOptions();
22
+ }
23
+ get datasetIdPropName() {
24
+ return this.gridOptions.datasetIdPropertyName || 'id';
25
+ }
26
+ get eventHandler() {
27
+ return this._eventHandler;
28
+ }
29
+ set eventHandler(eventHandler) {
30
+ this._eventHandler = eventHandler;
31
+ }
32
+ /** Getter for the Grid Options pulled through the Grid Object */
33
+ get gridOptions() {
34
+ return (this._grid?.getOptions() || {});
35
+ }
36
+ get rowDetailViewOptions() {
37
+ return this.gridOptions.rowDetailView;
38
+ }
39
+ addRxJsResource(rxjs) {
40
+ this.rxjs = rxjs;
41
+ }
42
+ /** Dispose of the RowDetailView Extension */
43
+ dispose() {
44
+ this.disposeAllViewComponents();
45
+ this._subscriptions = unsubscribeAll(this._subscriptions); // also unsubscribe all RxJS subscriptions
46
+ super.dispose();
47
+ }
48
+ /** Dispose of all the opened Row Detail Panels Angular View Components */
49
+ disposeAllViewComponents() {
50
+ this._views.forEach((compRef) => this.disposeViewComponent(compRef));
51
+ this._views = [];
52
+ }
53
+ /** Get the instance of the SlickGrid addon (control or plugin). */
54
+ getAddonInstance() {
55
+ return this;
56
+ }
57
+ init(grid) {
58
+ this._grid = grid;
59
+ super.init(this._grid);
60
+ this.register(grid?.getSelectionModel());
61
+ }
62
+ /**
63
+ * Create the plugin before the Grid creation, else it will behave oddly.
64
+ * Mostly because the column definitions might change after the grid creation
65
+ */
66
+ register(rowSelectionPlugin) {
67
+ if (typeof this.gridOptions.rowDetailView?.process === 'function') {
68
+ // we need to keep the user "process" method and replace it with our own execution method
69
+ // we do this because when we get the item detail, we need to call "onAsyncResponse.notify" for the plugin to work
70
+ this._userProcessFn = this.gridOptions.rowDetailView.process; // keep user's process method
71
+ this.gridOptions.rowDetailView.process = (item) => this.onProcessing(item); // replace process method & run our internal one
72
+ }
73
+ else {
74
+ throw new Error('[Angular-Slickgrid] You need to provide a "process" function for the Row Detail Extension to work properly');
75
+ }
76
+ if (this._grid && this.gridOptions?.rowDetailView) {
77
+ // load the Preload & RowDetail Templates (could be straight HTML or Angular View/ViewModel)
78
+ // when those are Angular View/ViewModel, we need to create View Component & provide the html containers to the Plugin (preTemplate/postTemplate methods)
79
+ if (!this.gridOptions.rowDetailView.preTemplate) {
80
+ this._preloadComponent = this.gridOptions?.rowDetailView?.preloadComponent;
81
+ this.gridOptions.rowDetailView.preTemplate = () => DOMPurify.sanitize(`<div class="${PRELOAD_CONTAINER_PREFIX}"></div>`);
82
+ }
83
+ if (!this.gridOptions.rowDetailView.postTemplate) {
84
+ this._viewComponent = this.gridOptions?.rowDetailView?.viewComponent;
85
+ this.gridOptions.rowDetailView.postTemplate = (itemDetail) => DOMPurify.sanitize(`<div class="${ROW_DETAIL_CONTAINER_PREFIX}${itemDetail[this.datasetIdPropName]}"></div>`);
86
+ }
87
+ // this also requires the Row Selection Model to be registered as well
88
+ if (!rowSelectionPlugin || !this._grid.getSelectionModel()) {
89
+ rowSelectionPlugin = new SlickRowSelectionModel(this.gridOptions.rowSelectionOptions || { selectActiveRow: true });
90
+ this._grid.setSelectionModel(rowSelectionPlugin);
91
+ }
92
+ // hook all events
93
+ if (this._grid && this.rowDetailViewOptions) {
94
+ if (this.rowDetailViewOptions.onExtensionRegistered) {
95
+ this.rowDetailViewOptions.onExtensionRegistered(this);
96
+ }
97
+ if (this.onAsyncResponse) {
98
+ this._eventHandler.subscribe(this.onAsyncResponse, (event, args) => {
99
+ if (this.rowDetailViewOptions && typeof this.rowDetailViewOptions.onAsyncResponse === 'function') {
100
+ this.rowDetailViewOptions.onAsyncResponse(event, args);
101
+ }
102
+ });
103
+ }
104
+ if (this.onAsyncEndUpdate) {
105
+ this._eventHandler.subscribe(this.onAsyncEndUpdate, (e, args) => {
106
+ // triggers after backend called "onAsyncResponse.notify()"
107
+ this.renderViewModel(args?.item);
108
+ if (this.rowDetailViewOptions && typeof this.rowDetailViewOptions.onAsyncEndUpdate === 'function') {
109
+ this.rowDetailViewOptions.onAsyncEndUpdate(e, args);
110
+ }
111
+ });
112
+ }
113
+ if (this.onAfterRowDetailToggle) {
114
+ this._eventHandler.subscribe(this.onAfterRowDetailToggle, (e, args) => {
115
+ // display preload template & re-render all the other Detail Views after toggling
116
+ // the preload View will eventually go away once the data gets loaded after the "onAsyncEndUpdate" event
117
+ this.renderPreloadView();
118
+ this.renderAllViewComponents();
119
+ if (this.rowDetailViewOptions && typeof this.rowDetailViewOptions.onAfterRowDetailToggle === 'function') {
120
+ this.rowDetailViewOptions.onAfterRowDetailToggle(e, args);
121
+ }
122
+ });
123
+ }
124
+ if (this.onBeforeRowDetailToggle) {
125
+ this._eventHandler.subscribe(this.onBeforeRowDetailToggle, (e, args) => {
126
+ // before toggling row detail, we need to create View Component if it doesn't exist
127
+ this.handleOnBeforeRowDetailToggle(e, args);
128
+ if (this.rowDetailViewOptions && typeof this.rowDetailViewOptions.onBeforeRowDetailToggle === 'function') {
129
+ this.rowDetailViewOptions.onBeforeRowDetailToggle(e, args);
130
+ }
131
+ });
132
+ }
133
+ if (this.onRowBackToViewportRange) {
134
+ this._eventHandler.subscribe(this.onRowBackToViewportRange, (e, args) => {
135
+ // when row is back to viewport range, we will re-render the View Component(s)
136
+ this.handleOnRowBackToViewportRange(e, args);
137
+ if (this.rowDetailViewOptions && typeof this.rowDetailViewOptions.onRowBackToViewportRange === 'function') {
138
+ this.rowDetailViewOptions.onRowBackToViewportRange(e, args);
139
+ }
140
+ });
141
+ }
142
+ if (this.onRowOutOfViewportRange) {
143
+ this._eventHandler.subscribe(this.onRowOutOfViewportRange, (e, args) => {
144
+ if (this.rowDetailViewOptions && typeof this.rowDetailViewOptions.onRowOutOfViewportRange === 'function') {
145
+ this.rowDetailViewOptions.onRowOutOfViewportRange(e, args);
146
+ }
147
+ });
148
+ }
149
+ // --
150
+ // hook some events needed by the Plugin itself
151
+ // we need to redraw the open detail views if we change column position (column reorder)
152
+ this._eventHandler.subscribe(this._grid.onColumnsReordered, this.redrawAllViewComponents.bind(this));
153
+ // on row selection changed, we also need to redraw
154
+ if (this.gridOptions.enableRowSelection || this.gridOptions.enableCheckboxSelector) {
155
+ this._eventHandler.subscribe(this._grid.onSelectedRowsChanged, this.redrawAllViewComponents.bind(this));
156
+ }
157
+ // on sort, all row detail are collapsed so we can dispose of all the Views as well
158
+ this._eventHandler.subscribe(this._grid.onSort, this.disposeAllViewComponents.bind(this));
159
+ // on filter changed, we need to re-render all Views
160
+ this._subscriptions.push(this.eventPubSubService?.subscribe('onFilterChanged', this.redrawAllViewComponents.bind(this)), this.eventPubSubService?.subscribe('onGridMenuClearAllFilters', () => setTimeout(() => this.redrawAllViewComponents())), this.eventPubSubService?.subscribe('onGridMenuClearAllSorting', () => setTimeout(() => this.redrawAllViewComponents())));
161
+ }
162
+ }
163
+ return this;
164
+ }
165
+ /** Redraw (re-render) all the expanded row detail View Components */
166
+ redrawAllViewComponents() {
167
+ this._views.forEach((compRef) => {
168
+ this.redrawViewComponent(compRef);
169
+ });
170
+ }
171
+ /** Render all the expanded row detail View Components */
172
+ renderAllViewComponents() {
173
+ this._views.forEach((view) => {
174
+ if (view && view.dataContext) {
175
+ this.renderViewModel(view.dataContext);
176
+ }
177
+ });
178
+ }
179
+ /** Redraw the necessary View Component */
180
+ redrawViewComponent(createdView) {
181
+ const containerElements = this.gridContainerElement.getElementsByClassName(`${ROW_DETAIL_CONTAINER_PREFIX}${createdView.id}`);
182
+ if (containerElements && containerElements.length >= 0) {
183
+ this.renderViewModel(createdView.dataContext);
184
+ }
185
+ }
186
+ /** Render (or re-render) the View Component (Row Detail) */
187
+ renderPreloadView() {
188
+ const containerElements = this.gridContainerElement.getElementsByClassName(`${PRELOAD_CONTAINER_PREFIX}`);
189
+ if (containerElements && containerElements.length >= 0) {
190
+ this.angularUtilService.createAngularComponentAppendToDom(this._preloadComponent, containerElements[containerElements.length - 1], true);
191
+ }
192
+ }
193
+ /** Render (or re-render) the View Component (Row Detail) */
194
+ renderViewModel(item) {
195
+ const containerElements = this.gridContainerElement.getElementsByClassName(`${ROW_DETAIL_CONTAINER_PREFIX}${item[this.datasetIdPropName]}`);
196
+ if (containerElements && containerElements.length > 0) {
197
+ const componentOutput = this.angularUtilService.createAngularComponentAppendToDom(this._viewComponent, containerElements[containerElements.length - 1], true);
198
+ if (componentOutput && componentOutput.componentRef && componentOutput.componentRef.instance) {
199
+ // pass a few properties to the Row Detail template component
200
+ Object.assign(componentOutput.componentRef.instance, {
201
+ model: item,
202
+ addon: this,
203
+ grid: this._grid,
204
+ dataView: this.dataView,
205
+ parent: this.rowDetailViewOptions && this.rowDetailViewOptions.parent,
206
+ });
207
+ const viewObj = this._views.find(obj => obj.id === item[this.datasetIdPropName]);
208
+ if (viewObj) {
209
+ viewObj.componentRef = componentOutput.componentRef;
210
+ }
211
+ return viewObj;
212
+ }
213
+ }
214
+ return undefined;
215
+ }
216
+ // --
217
+ // protected functions
218
+ // ------------------
219
+ disposeViewComponent(expandedView) {
220
+ const compRef = expandedView?.componentRef;
221
+ if (compRef) {
222
+ this.appRef.detachView(compRef.hostView);
223
+ if (compRef?.destroy) {
224
+ compRef.destroy();
225
+ }
226
+ return expandedView;
227
+ }
228
+ }
229
+ /**
230
+ * notify the onAsyncResponse with the "args.item" (required property)
231
+ * the plugin will then use item to populate the row detail panel with the "postTemplate"
232
+ * @param item
233
+ */
234
+ notifyTemplate(item) {
235
+ if (this.onAsyncResponse) {
236
+ this.onAsyncResponse.notify({ item }, undefined, this);
237
+ }
238
+ }
239
+ /**
240
+ * On Processing, we will notify the plugin with the new item detail once backend server call completes
241
+ * @param item
242
+ */
243
+ async onProcessing(item) {
244
+ if (item && typeof this._userProcessFn === 'function') {
245
+ let awaitedItemDetail;
246
+ const userProcessFn = this._userProcessFn(item);
247
+ // wait for the "userProcessFn", once resolved we will save it into the "collection"
248
+ const response = await userProcessFn;
249
+ if (response.hasOwnProperty(this.datasetIdPropName)) {
250
+ awaitedItemDetail = response; // from Promise
251
+ }
252
+ else if (response && response instanceof Observable || response instanceof Promise) {
253
+ awaitedItemDetail = await castObservableToPromise(this.rxjs, response); // from Angular-http-client
254
+ }
255
+ if (!awaitedItemDetail || !awaitedItemDetail.hasOwnProperty(this.datasetIdPropName)) {
256
+ throw new Error(`[Angular-Slickgrid] could not process the Row Detail, you must make sure that your "process" callback
257
+ (a Promise or an HttpClient call returning an Observable) returns an item object that has an "${this.datasetIdPropName}" property`);
258
+ }
259
+ // notify the plugin with the new item details
260
+ this.notifyTemplate(awaitedItemDetail || {});
261
+ }
262
+ }
263
+ /**
264
+ * Just before the row get expanded or collapsed we will do the following
265
+ * First determine if the row is expanding or collapsing,
266
+ * if it's expanding we will add it to our View Components reference array if we don't already have it
267
+ * or if it's collapsing we will remove it from our View Components reference array
268
+ */
269
+ handleOnBeforeRowDetailToggle(e, args) {
270
+ // expanding
271
+ if (args && args.item && args.item.__collapsed) {
272
+ // expanding row detail
273
+ const viewInfo = {
274
+ id: args.item[this.datasetIdPropName],
275
+ dataContext: args.item
276
+ };
277
+ const idPropName = this.gridOptions.datasetIdPropertyName || 'id';
278
+ addToArrayWhenNotExists(this._views, viewInfo, idPropName);
279
+ }
280
+ else {
281
+ // collapsing, so dispose of the View/Component
282
+ const foundViewIndex = this._views.findIndex((view) => view.id === args.item[this.datasetIdPropName]);
283
+ if (foundViewIndex >= 0 && this._views.hasOwnProperty(foundViewIndex)) {
284
+ const compRef = this._views[foundViewIndex].componentRef;
285
+ if (compRef) {
286
+ this.appRef.detachView(compRef.hostView);
287
+ compRef.destroy();
288
+ }
289
+ this._views.splice(foundViewIndex, 1);
290
+ }
291
+ }
292
+ }
293
+ /** When Row comes back to Viewport Range, we need to redraw the View */
294
+ handleOnRowBackToViewportRange(e, args) {
295
+ if (args?.item) {
296
+ this.redrawAllViewComponents();
297
+ }
298
+ }
299
+ }
300
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2xpY2tSb3dEZXRhaWxWaWV3LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vc3JjL2FwcC9tb2R1bGVzL2FuZ3VsYXItc2xpY2tncmlkL2V4dGVuc2lvbnMvc2xpY2tSb3dEZXRhaWxWaWV3LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sdUNBQXVDLENBQUM7QUFDL0MsT0FBTywyQ0FBMkMsQ0FBQztBQUduRCxPQUFPLEVBQ0wsdUJBQXVCLEVBQ3ZCLHVCQUF1QixFQUt2QixzQkFBc0IsRUFDdEIsY0FBYyxHQUNmLE1BQU0sNkJBQTZCLENBQUM7QUFFckMsT0FBTyxFQUFFLGtCQUFrQixJQUFJLDJCQUEyQixFQUFFLE1BQU0sNkNBQTZDLENBQUM7QUFDaEgsT0FBTyxFQUFFLFVBQVUsRUFBVyxNQUFNLE1BQU0sQ0FBQztBQUMzQyxPQUFPLEtBQUssU0FBUyxNQUFNLFdBQVcsQ0FBQztBQUt2QyxNQUFNLDJCQUEyQixHQUFHLFlBQVksQ0FBQztBQUNqRCxNQUFNLHdCQUF3QixHQUFHLG1CQUFtQixDQUFDO0FBUXJELE1BQU0sT0FBTyxrQkFBbUIsU0FBUSwyQkFBMkI7SUFTakUsWUFDcUIsa0JBQXNDLEVBQ3RDLE1BQXNCLEVBQ3RCLGtCQUFzQyxFQUN0QyxvQkFBb0MsRUFDN0MsSUFBaUI7UUFFM0IsS0FBSyxFQUFFLENBQUM7UUFOVyx1QkFBa0IsR0FBbEIsa0JBQWtCLENBQW9CO1FBQ3RDLFdBQU0sR0FBTixNQUFNLENBQWdCO1FBQ3RCLHVCQUFrQixHQUFsQixrQkFBa0IsQ0FBb0I7UUFDdEMseUJBQW9CLEdBQXBCLG9CQUFvQixDQUFnQjtRQUM3QyxTQUFJLEdBQUosSUFBSSxDQUFhO1FBVm5CLFdBQU0sR0FBa0IsRUFBRSxDQUFDO1FBRTNCLG1CQUFjLEdBQXdCLEVBQUUsQ0FBQztJQVduRCxDQUFDO0lBRUQsSUFBSSxZQUFZO1FBQ2QsT0FBTyxJQUFJLENBQUMsVUFBVSxFQUFFLENBQUM7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RyxJQUFJLENBQUMsTUFBTSxDQUFDLFNBQVMsQ0FBQyxDQUFDLElBQWlCLEVBQUUsRUFBRSxDQUFDLElBQUksQ0FBQyxFQUFFLEtBQUssSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsaUJBQWlCLENBQUMsQ0FBQyxDQUFDO1lBQ25ILElBQUksY0FBYyxJQUFJLENBQUMsSUFBSSxJQUFJLENBQUMsTUFBTSxDQUFDLGNBQWMsQ0FBQyxjQUFjLENBQUMsRUFBRTtnQkFDckUsTUFBTSxPQUFPLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQyxjQUFjLENBQUMsQ0FBQyxZQUFZLENBQUM7Z0JBQ3pELElBQUksT0FBTyxFQUFFO29CQUNYLElBQUksQ0FBQyxNQUFNLENBQUMsVUFBVSxDQUFDLE9BQU8sQ0FBQyxRQUFRLENBQUMsQ0FBQztvQkFDekMsT0FBTyxDQUFDLE9BQU8sRUFBRSxDQUFDO2lCQUNuQjtnQkFDRCxJQUFJLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxjQUFjLEVBQUUsQ0FBQyxDQUFDLENBQUM7YUFDdkM7U0FDRjtJQUNILENBQUM7SUFFRCx3RUFBd0U7SUFDOUQsOEJBQThCLENBQUMsQ0FBUSxFQUFFLElBQTBIO1FBQzNLLElBQUksSUFBSSxFQUFFLElBQUksRUFBRTtZQUNkLElBQUksQ0FBQyx1QkFBdUIsRUFBRSxDQUFDO1NBQ2hDO0lBQ0gsQ0FBQztDQUNGIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0ICdzbGlja2dyaWQvcGx1Z2lucy9zbGljay5yb3dkZXRhaWx2aWV3JztcclxuaW1wb3J0ICdzbGlja2dyaWQvcGx1Z2lucy9zbGljay5yb3dzZWxlY3Rpb25tb2RlbCc7XHJcblxyXG5pbXBvcnQgeyBBcHBsaWNhdGlvblJlZiwgQ29tcG9uZW50UmVmLCBUeXBlLCBWaWV3Q29udGFpbmVyUmVmIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XHJcbmltcG9ydCB7XHJcbiAgYWRkVG9BcnJheVdoZW5Ob3RFeGlzdHMsXHJcbiAgY2FzdE9ic2VydmFibGVUb1Byb21pc2UsXHJcbiAgRXZlbnRTdWJzY3JpcHRpb24sXHJcbiAgUnhKc0ZhY2FkZSxcclxuICBTbGlja0V2ZW50SGFuZGxlcixcclxuICBTbGlja0dyaWQsXHJcbiAgU2xpY2tSb3dTZWxlY3Rpb25Nb2RlbCxcclxuICB1bnN1YnNjcmliZUFsbCxcclxufSBmcm9tICdAc2xpY2tncmlkLXVuaXZlcnNhbC9jb21tb24nO1xyXG5pbXBvcnQgeyBFdmVudFB1YlN1YlNlcnZpY2UgfSBmcm9tICdAc2xpY2tncmlkLXVuaXZlcnNhbC9ldmVudC1wdWItc3ViJztcclxuaW1wb3J0IHsgU2xpY2tSb3dEZXRhaWxWaWV3IGFzIFVuaXZlcnNhbFNsaWNrUm93RGV0YWlsVmlldyB9IGZyb20gJ0BzbGlja2dyaWQtdW5pdmVyc2FsL3Jvdy1kZXRhaWwtdmlldy1wbHVnaW4nO1xyXG5pbXBvcnQgeyBPYnNlcnZhYmxlLCBTdWJqZWN0IH0gZnJvbSAncnhqcyc7XHJcbmltcG9ydCAqIGFzIERPTVB1cmlmeSBmcm9tICdkb21wdXJpZnknO1xyXG5cclxuaW1wb3J0IHsgR3JpZE9wdGlvbiwgUm93RGV0YWlsVmlldyB9IGZyb20gJy4uL21vZGVscy9pbmRleCc7XHJcbmltcG9ydCB7IEFuZ3VsYXJVdGlsU2VydmljZSB9IGZyb20gJy4uL3NlcnZpY2VzL2FuZ3VsYXJVdGlsLnNlcnZpY2UnO1xyXG5cclxuY29uc3QgUk9XX0RFVEFJTF9DT05UQUlORVJfUFJFRklYID0gJ2NvbnRhaW5lcl8nO1xyXG5jb25zdCBQUkVMT0FEX0NPTlRBSU5FUl9QUkVGSVggPSAnY29udGFpbmVyX2xvYWRpbmcnO1xyXG5cclxuZXhwb3J0IGludGVyZmFjZSBDcmVhdGVkVmlldyB7XHJcbiAgaWQ6IHN0cmluZyB8IG51bWJlcjtcclxuICBkYXRhQ29udGV4dDogYW55O1xyXG4gIGNvbXBvbmVudFJlZj86IENvbXBvbmVudFJlZjxhbnk+O1xyXG59XHJcblxyXG5leHBvcnQgY2xhc3MgU2xpY2tSb3dEZXRhaWxWaWV3IGV4dGVuZHMgVW5pdmVyc2FsU2xpY2tSb3dEZXRhaWxWaWV3IHtcclxuICByb3dEZXRhaWxDb250YWluZXIhOiBWaWV3Q29udGFpbmVyUmVmO1xyXG4gIHByb3RlY3RlZCBfZXZlbnRIYW5kbGVyITogU2xpY2tFdmVudEhhbmRsZXI7XHJcbiAgcHJvdGVjdGVkIF9wcmVsb2FkQ29tcG9uZW50OiBUeXBlPG9iamVjdD4gfCB1bmRlZmluZWQ7XHJcbiAgcHJvdGVjdGVkIF92aWV3czogQ3JlYXRlZFZpZXdbXSA9IFtdO1xyXG4gIHByb3RlY3RlZCBfdmlld0NvbXBvbmVudCE6IFR5cGU8b2JqZWN0PjtcclxuICBwcm90ZWN0ZWQgX3N1YnNjcmlwdGlvbnM6IEV2ZW50U3Vic2NyaXB0aW9uW10gPSBbXTtcclxuICBwcm90ZWN0ZWQgX3VzZXJQcm9jZXNzRm4hOiAoaXRlbTogYW55KSA9PiBQcm9taXNlPGFueT4gfCBPYnNlcnZhYmxlPGFueT4gfCBTdWJqZWN0PGFueT47XHJcblxyXG4gIGNvbnN0cnVjdG9yKFxyXG4gICAgcHJvdGVjdGVkIHJlYWRvbmx5IGFuZ3VsYXJVdGlsU2VydmljZTogQW5ndWxhclV0aWxTZXJ2aWNlLFxyXG4gICAgcHJvdGVjdGVkIHJlYWRvbmx5IGFwcFJlZjogQXBwbGljYXRpb25SZWYsXHJcbiAgICBwcm90ZWN0ZWQgcmVhZG9ubHkgZXZlbnRQdWJTdWJTZXJ2aWNlOiBFdmVudFB1YlN1YlNlcnZpY2UsXHJcbiAgICBwcm90ZWN0ZWQgcmVhZG9ubHkgZ3JpZENvbnRhaW5lckVsZW1lbnQ6IEhUTUxEaXZFbGVtZW50LFxyXG4gICAgcHJvdGVjdGVkIHJ4anM/OiBSeEpzRmFjYWRlLFxyXG4gICkge1xyXG4gICAgc3VwZXIoKTtcclxuICB9XHJcblxyXG4gIGdldCBhZGRvbk9wdGlvbnMoKSB7XHJcbiAgICByZXR1cm4gdGhpcy5nZXRPcHRpb25zKCk7XHJcbiAgfVxyXG5cclxuICBwcm90ZWN0ZWQgZ2V0IGRhdGFzZXRJZFByb3BOYW1lKCk6IHN0cmluZyB7XHJcbiAgICByZXR1cm4gdGhpcy5ncmlkT3B0aW9ucy5kYXRhc2V0SWRQcm9wZXJ0eU5hbWUgfHwgJ2lkJztcclxuICB9XHJcblxyXG4gIGdldCBldmVudEhhbmRsZXIoKTogU2xpY2tFdmVudEhhbmRsZXIge1xyXG4gICAgcmV0dXJuIHRoaXMuX2V2ZW50SGFuZGxlcjtcclxuICB9XHJcbiAgc2V0IGV2ZW50SGFuZGxlcihldmVudEhhbmRsZXI6IFNsaWNrRXZlbnRIYW5kbGVyKSB7XHJcbiAgICB0aGlzLl9ldmVudEhhbmRsZXIgPSBldmVudEhhbmRsZXI7XHJcbiAgfVxyXG5cclxuICAvKiogR2V0dGVyIGZvciB0aGUgR3JpZCBPcHRpb25zIHB1bGxlZCB0aHJvdWdoIHRoZSBHcmlkIE9iamVjdCAqL1xyXG4gIGdldCBncmlkT3B0aW9ucygpOiBHcmlkT3B0aW9uIHtcclxuICAgIHJldHVybiAodGhpcy5fZ3JpZD8uZ2V0T3B0aW9ucygpIHx8IHt9KSBhcyBHcmlkT3B0aW9uO1xyXG4gIH1cclxuXHJcbiAgZ2V0IHJvd0RldGFpbFZpZXdPcHRpb25zKCk6IFJvd0RldGFpbFZpZXcgfCB1bmRlZmluZWQge1xyXG4gICAgcmV0dXJuIHRoaXMuZ3JpZE9wdGlvbnMucm93RGV0YWlsVmlldztcclxuICB9XHJcblxyXG4gIGFkZFJ4SnNSZXNvdXJjZShyeGpzOiBSeEpzRmFjYWRlKSB7XHJcbiAgICB0aGlzLnJ4anMgPSByeGpzO1xyXG4gIH1cclxuXHJcbiAgLyoqIERpc3Bvc2Ugb2YgdGhlIFJvd0RldGFpbFZpZXcgRXh0ZW5zaW9uICovXHJcbiAgZGlzcG9zZSgpIHtcclxuICAgIHRoaXMuZGlzcG9zZUFsbFZpZXdDb21wb25lbnRzKCk7XHJcbiAgICB0aGlzLl9zdWJzY3JpcHRpb25zID0gdW5zdWJzY3JpYmVBbGwodGhpcy5fc3Vic2NyaXB0aW9ucyk7IC8vIGFsc28gdW5zdWJzY3JpYmUgYWxsIFJ4SlMgc3Vic2NyaXB0aW9uc1xyXG4gICAgc3VwZXIuZGlzcG9zZSgpO1xyXG4gIH1cclxuXHJcbiAgLyoqIERpc3Bvc2Ugb2YgYWxsIHRoZSBvcGVuZWQgUm93IERldGFpbCBQYW5lbHMgQW5ndWxhciBWaWV3IENvbXBvbmVudHMgKi9cclxuICBkaXNwb3NlQWxsVmlld0NvbXBvbmVudHMoKSB7XHJcbiAgICB0aGlzLl92aWV3cy5mb3JFYWNoKChjb21wUmVmKSA9PiB0aGlzLmRpc3Bvc2VWaWV3Q29tcG9uZW50KGNvbXBSZWYpKTtcclxuICAgIHRoaXMuX3ZpZXdzID0gW107XHJcbiAgfVxyXG5cclxuICAvKiogR2V0IHRoZSBpbnN0YW5jZSBvZiB0aGUgU2xpY2tHcmlkIGFkZG9uIChjb250cm9sIG9yIHBsdWdpbikuICovXHJcbiAgZ2V0QWRkb25JbnN0YW5jZSgpOiBTbGlja1Jvd0RldGFpbFZpZXcgfCBudWxsIHtcclxuICAgIHJldHVybiB0aGlzO1xyXG4gIH1cclxuXHJcbiAgaW5pdChncmlkOiBTbGlja0dyaWQpIHtcclxuICAgIHRoaXMuX2dyaWQgPSBncmlkO1xyXG4gICAgc3VwZXIuaW5pdCh0aGlzLl9ncmlkKTtcclxuICAgIHRoaXMucmVnaXN0ZXIoZ3JpZD8uZ2V0U2VsZWN0aW9uTW9kZWwoKSk7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBDcmVhdGUgdGhlIHBsdWdpbiBiZWZvcmUgdGhlIEdyaWQgY3JlYXRpb24sIGVsc2UgaXQgd2lsbCBiZWhhdmUgb2RkbHkuXHJcbiAgICogTW9zdGx5IGJlY2F1c2UgdGhlIGNvbHVtbiBkZWZpbml0aW9ucyBtaWdodCBjaGFuZ2UgYWZ0ZXIgdGhlIGdyaWQgY3JlYXRpb25cclxuICAgKi9cclxuICByZWdpc3Rlcihyb3dTZWxlY3Rpb25QbHVnaW4/OiBTbGlja1Jvd1NlbGVjdGlvbk1vZGVsKSB7XHJcbiAgICBpZiAodHlwZW9mIHRoaXMuZ3JpZE9wdGlvbnMucm93RGV0YWlsVmlldz8ucHJvY2VzcyA9PT0gJ2Z1bmN0aW9uJykge1xyXG4gICAgICAvLyB3ZSBuZWVkIHRvIGtlZXAgdGhlIHVzZXIgXCJwcm9jZXNzXCIgbWV0aG9kIGFuZCByZXBsYWNlIGl0IHdpdGggb3VyIG93biBleGVjdXRpb24gbWV0aG9kXHJcbiAgICAgIC8vIHdlIGRvIHRoaXMgYmVjYXVzZSB3aGVuIHdlIGdldCB0aGUgaXRlbSBkZXRhaWwsIHdlIG5lZWQgdG8gY2FsbCBcIm9uQXN5bmNSZXNwb25zZS5ub3RpZnlcIiBmb3IgdGhlIHBsdWdpbiB0byB3b3JrXHJcbiAgICAgIHRoaXMuX3VzZXJQcm9jZXNzRm4gPSB0aGlzLmdyaWRPcHRpb25zLnJvd0RldGFpbFZpZXcucHJvY2VzcyBhcyAoaXRlbTogYW55KSA9PiBQcm9taXNlPGFueT47ICAgICAgICAgICAgICAgIC8vIGtlZXAgdXNlcidzIHByb2Nlc3MgbWV0aG9kXHJcbiAgICAgIHRoaXMuZ3JpZE9wdGlvbnMucm93RGV0YWlsVmlldy5wcm9jZXNzID0gKGl0ZW0pID0+IHRoaXMub25Qcm9jZXNzaW5nKGl0ZW0pOyAgLy8gcmVwbGFjZSBwcm9jZXNzIG1ldGhvZCAmIHJ1biBvdXIgaW50ZXJuYWwgb25lXHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ1tBbmd1bGFyLVNsaWNrZ3JpZF0gWW91IG5lZWQgdG8gcHJvdmlkZSBhIFwicHJvY2Vzc1wiIGZ1bmN0aW9uIGZvciB0aGUgUm93IERldGFpbCBFeHRlbnNpb24gdG8gd29yayBwcm9wZXJseScpO1xyXG4gICAgfVxyXG5cclxuICAgIGlmICh0aGlzLl9ncmlkICYmIHRoaXMuZ3JpZE9wdGlvbnM/LnJvd0RldGFpbFZpZXcpIHtcclxuICAgICAgLy8gbG9hZCB0aGUgUHJlbG9hZCAmIFJvd0RldGFpbCBUZW1wbGF0ZXMgKGNvdWxkIGJlIHN0cmFpZ2h0IEhUTUwgb3IgQW5ndWxhciBWaWV3L1ZpZXdNb2RlbClcclxuICAgICAgLy8gd2hlbiB0aG9zZSBhcmUgQW5ndWxhciBWaWV3L1ZpZXdNb2RlbCwgd2UgbmVlZCB0byBjcmVhdGUgVmlldyBDb21wb25lbnQgJiBwcm92aWRlIHRoZSBodG1sIGNvbnRhaW5lcnMgdG8gdGhlIFBsdWdpbiAocHJlVGVtcGxhdGUvcG9zdFRlbXBsYXRlIG1ldGhvZHMpXHJcbiAgICAgIGlmICghdGhpcy5ncmlkT3B0aW9ucy5yb3dEZXRhaWxWaWV3LnByZVRlbXBsYXRlKSB7XHJcbiAgICAgICAgdGhpcy5fcHJlbG9hZENvbXBvbmVudCA9IHRoaXMuZ3JpZE9wdGlvbnM/LnJvd0RldGFpbFZpZXc/LnByZWxvYWRDb21wb25lbnQ7XHJcbiAgICAgICAgdGhpcy5ncmlkT3B0aW9ucy5yb3dEZXRhaWxWaWV3LnByZVRlbXBsYXRlID0gKCkgPT4gRE9NUHVyaWZ5LnNhbml0aXplKGA8ZGl2IGNsYXNzPVwiJHtQUkVMT0FEX0NPTlRBSU5FUl9QUkVGSVh9XCI+PC9kaXY+YCk7XHJcbiAgICAgIH1cclxuICAgICAgaWYgKCF0aGlzLmdyaWRPcHRpb25zLnJvd0RldGFpbFZpZXcucG9zdFRlbXBsYXRlKSB7XHJcbiAgICAgICAgdGhpcy5fdmlld0NvbXBvbmVudCA9IHRoaXMuZ3JpZE9wdGlvbnM/LnJvd0RldGFpbFZpZXc/LnZpZXdDb21wb25lbnQ7XHJcbiAgICAgICAgdGhpcy5ncmlkT3B0aW9ucy5yb3dEZXRhaWxWaWV3LnBvc3RUZW1wbGF0ZSA9IChpdGVtRGV0YWlsOiBhbnkpID0+IERPTVB1cmlmeS5zYW5pdGl6ZShgPGRpdiBjbGFzcz1cIiR7Uk9XX0RFVEFJTF9DT05UQUlORVJfUFJFRklYfSR7aXRlbURldGFpbFt0aGlzLmRhdGFzZXRJZFByb3BOYW1lXX1cIj48L2Rpdj5gKTtcclxuICAgICAgfVxyXG5cclxuICAgICAgLy8gdGhpcyBhbHNvIHJlcXVpcmVzIHRoZSBSb3cgU2VsZWN0aW9uIE1vZGVsIHRvIGJlIHJlZ2lzdGVyZWQgYXMgd2VsbFxyXG4gICAgICBpZiAoIXJvd1NlbGVjdGlvblBsdWdpbiB8fCAhdGhpcy5fZ3JpZC5nZXRTZWxlY3Rpb25Nb2RlbCgpKSB7XHJcbiAgICAgICAgcm93U2VsZWN0aW9uUGx1Z2luID0gbmV3IFNsaWNrUm93U2VsZWN0aW9uTW9kZWwodGhpcy5ncmlkT3B0aW9ucy5yb3dTZWxlY3Rpb25PcHRpb25zIHx8IHsgc2VsZWN0QWN0aXZlUm93OiB0cnVlIH0pO1xyXG4gICAgICAgIHRoaXMuX2dyaWQuc2V0U2VsZWN0aW9uTW9kZWwocm93U2VsZWN0aW9uUGx1Z2luKTtcclxuICAgICAgfVxyXG5cclxuICAgICAgLy8gaG9vayBhbGwgZXZlbnRzXHJcbiAgICAgIGlmICh0aGlzLl9ncmlkICYmIHRoaXMucm93RGV0YWlsVmlld09wdGlvbnMpIHtcclxuICAgICAgICBpZiAodGhpcy5yb3dEZXRhaWxWaWV3T3B0aW9ucy5vbkV4dGVuc2lvblJlZ2lzdGVyZWQpIHtcclxuICAgICAgICAgIHRoaXMucm93RGV0YWlsVmlld09wdGlvbnMub25FeHRlbnNpb25SZWdpc3RlcmVkKHRoaXMpO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgaWYgKHRoaXMub25Bc3luY1Jlc3BvbnNlKSB7XHJcbiAgICAgICAgICB0aGlzLl9ldmVudEhhbmRsZXIuc3Vic2NyaWJlKHRoaXMub25Bc3luY1Jlc3BvbnNlLCAoZXZlbnQsIGFyZ3MpID0+IHtcclxuICAgICAgICAgICAgaWYgKHRoaXMucm93RGV0YWlsVmlld09wdGlvbnMgJiYgdHlwZW9mIHRoaXMucm93RGV0YWlsVmlld09wdGlvbnMub25Bc3luY1Jlc3BvbnNlID09PSAnZnVuY3Rpb24nKSB7XHJcbiAgICAgICAgICAgICAgdGhpcy5yb3dEZXRhaWxWaWV3T3B0aW9ucy5vbkFzeW5jUmVzcG9uc2UoZXZlbnQsIGFyZ3MpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICB9KTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGlmICh0aGlzLm9uQXN5bmNFbmRVcGRhdGUpIHtcclxuICAgICAgICAgIHRoaXMuX2V2ZW50SGFuZGxlci5zdWJzY3JpYmUodGhpcy5vbkFzeW5jRW5kVXBkYXRlLCAoZTogYW55LCBhcmdzOiB7IGdyaWQ6IFNsaWNrR3JpZDsgaXRlbTogYW55OyB9KSA9PiB7XHJcbiAgICAgICAgICAgIC8vIHRyaWdnZXJzIGFmdGVyIGJhY2tlbmQgY2FsbGVkIFwib25Bc3luY1Jlc3BvbnNlLm5vdGlmeSgpXCJcclxuICAgICAgICAgICAgdGhpcy5yZW5kZXJWaWV3TW9kZWwoYXJncz8uaXRlbSk7XHJcblxyXG4gICAgICAgICAgICBpZiAodGhpcy5yb3dEZXRhaWxWaWV3T3B0aW9ucyAmJiB0eXBlb2YgdGhpcy5yb3dEZXRhaWxWaWV3T3B0aW9ucy5vbkFzeW5jRW5kVXBkYXRlID09PSAnZnVuY3Rpb24nKSB7XHJcbiAgICAgICAgICAgICAgdGhpcy5yb3dEZXRhaWxWaWV3T3B0aW9ucy5vbkFzeW5jRW5kVXBkYXRlKGUsIGFyZ3MpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICB9KTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGlmICh0aGlzLm9uQWZ0ZXJSb3dEZXRhaWxUb2dnbGUpIHtcclxuICAgICAgICAgIHRoaXMuX2V2ZW50SGFuZGxlci5zdWJzY3JpYmUodGhpcy5vbkFmdGVyUm93RGV0YWlsVG9nZ2xlLCAoZTogYW55LCBhcmdzOiB7IGdyaWQ6IFNsaWNrR3JpZDsgaXRlbTogYW55OyBleHBhbmRlZFJvd3M6IG51bWJlcltdOyB9KSA9PiB7XHJcbiAgICAgICAgICAgIC8vIGRpc3BsYXkgcHJlbG9hZCB0ZW1wbGF0ZSAmIHJlLXJlbmRlciBhbGwgdGhlIG90aGVyIERldGFpbCBWaWV3cyBhZnRlciB0b2dnbGluZ1xyXG4gICAgICAgICAgICAvLyB0aGUgcHJlbG9hZCBWaWV3IHdpbGwgZXZlbnR1YWxseSBnbyBhd2F5IG9uY2UgdGhlIGRhdGEgZ2V0cyBsb2FkZWQgYWZ0ZXIgdGhlIFwib25Bc3luY0VuZFVwZGF0ZVwiIGV2ZW50XHJcbiAgICAgICAgICAgIHRoaXMucmVuZGVyUHJlbG9hZFZpZXcoKTtcclxuICAgICAgICAgICAgdGhpcy5yZW5kZXJBbGxWaWV3Q29tcG9uZW50cygpO1xyXG5cclxuICAgICAgICAgICAgaWYgKHRoaXMucm93RGV0YWlsVmlld09wdGlvbnMgJiYgdHlwZW9mIHRoaXMucm93RGV0YWlsVmlld09wdGlvbnMub25BZnRlclJvd0RldGFpbFRvZ2dsZSA9PT0gJ2Z1bmN0aW9uJykge1xyXG4gICAgICAgICAgICAgIHRoaXMucm93RGV0YWlsVmlld09wdGlvbnMub25BZnRlclJvd0RldGFpbFRvZ2dsZShlLCBhcmdzKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgfSk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBpZiAodGhpcy5vbkJlZm9yZVJvd0RldGFpbFRvZ2dsZSkge1xyXG4gICAgICAgICAgdGhpcy5fZXZlbnRIYW5kbGVyLnN1YnNjcmliZSh0aGlzLm9uQmVmb3JlUm93RGV0YWlsVG9nZ2xlLCAoZSwgYXJncykgPT4ge1xyXG4gICAgICAgICAgICAvLyBiZWZvcmUgdG9nZ2xpbmcgcm93IGRldGFpbCwgd2UgbmVlZCB0byBjcmVhdGUgVmlldyBDb21wb25lbnQgaWYgaXQgZG9lc24ndCBleGlzdFxyXG4gICAgICAgICAgICB0aGlzLmhhbmRsZU9uQmVmb3JlUm93RGV0YWlsVG9nZ2xlKGUsIGFyZ3MpO1xyXG5cclxuICAgICAgICAgICAgaWYgKHRoaXMucm93RGV0YWlsVmlld09wdGlvbnMgJiYgdHlwZW9mIHRoaXMucm93RGV0YWlsVmlld09wdGlvbnMub25CZWZvcmVSb3dEZXRhaWxUb2dnbGUgPT09ICdmdW5jdGlvbicpIHtcclxuICAgICAgICAgICAgICB0aGlzLnJvd0RldGFpbFZpZXdPcHRpb25zLm9uQmVmb3JlUm93RGV0YWlsVG9nZ2xlKGUsIGFyZ3MpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICB9KTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGlmICh0aGlzLm9uUm93QmFja1RvVmlld3BvcnRSYW5nZSkge1xyXG4gICAgICAgICAgdGhpcy5fZXZlbnRIYW5kbGVyLnN1YnNjcmliZSh0aGlzLm9uUm93QmFja1RvVmlld3BvcnRSYW5nZSwgKGU6IGFueSwgYXJnczogeyBncmlkOiBTbGlja0dyaWQ7IGl0ZW06IGFueTsgcm93SWQ6IG51bWJlcjsgcm93SW5kZXg6IG51bWJlcjsgZXhwYW5kZWRSb3dzOiBhbnlbXTsgcm93SWRzT3V0T2ZWaWV3cG9ydDogbnVtYmVyW107IH0pID0+IHtcclxuICAgICAgICAgICAgLy8gd2hlbiByb3cgaXMgYmFjayB0byB2aWV3cG9ydCByYW5nZSwgd2Ugd2lsbCByZS1yZW5kZXIgdGhlIFZpZXcgQ29tcG9uZW50KHMpXHJcbiAgICAgICAgICAgIHRoaXMuaGFuZGxlT25Sb3dCYWNrVG9WaWV3cG9ydFJhbmdlKGUsIGFyZ3MpO1xyXG5cclxuICAgICAgICAgICAgaWYgKHRoaXMucm93RGV0YWlsVmlld09wdGlvbnMgJiYgdHlwZW9mIHRoaXMucm93RGV0YWlsVmlld09wdGlvbnMub25Sb3dCYWNrVG9WaWV3cG9ydFJhbmdlID09PSAnZnVuY3Rpb24nKSB7XHJcbiAgICAgICAgICAgICAgdGhpcy5yb3dEZXRhaWxWaWV3T3B0aW9ucy5vblJvd0JhY2tUb1ZpZXdwb3J0UmFuZ2UoZSwgYXJncyk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgIH0pO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgaWYgKHRoaXMub25Sb3dPdXRPZlZpZXdwb3J0UmFuZ2UpIHtcclxuICAgICAgICAgIHRoaXMuX2V2ZW50SGFuZGxlci5zdWJzY3JpYmUodGhpcy5vblJvd091dE9mVmlld3BvcnRSYW5nZSwgKGU6IGFueSwgYXJnczogeyBncmlkOiBTbGlja0dyaWQ7IGl0ZW06IGFueTsgcm93SWQ6IG51bWJlcjsgcm93SW5kZXg6IG51bWJlcjsgZXhwYW5kZWRSb3dzOiBhbnlbXTsgcm93SWRzT3V0T2ZWaWV3cG9ydDogbnVtYmVyW107IH0pID0+IHtcclxuICAgICAgICAgICAgaWYgKHRoaXMucm93RGV0YWlsVmlld09wdGlvbnMgJiYgdHlwZW9mIHRoaXMucm93RGV0YWlsVmlld09wdGlvbnMub25Sb3dPdXRPZlZpZXdwb3J0UmFuZ2UgPT09ICdmdW5jdGlvbicpIHtcclxuICAgICAgICAgICAgICB0aGlzLnJvd0RldGFpbFZpZXdPcHRpb25zLm9uUm93T3V0T2ZWaWV3cG9ydFJhbmdlKGUsIGFyZ3MpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICB9KTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIC8vIC0tXHJcbiAgICAgICAgLy8gaG9vayBzb21lIGV2ZW50cyBuZWVkZWQgYnkgdGhlIFBsdWdpbiBpdHNlbGZcclxuXHJcbiAgICAgICAgLy8gd2UgbmVlZCB0byByZWRyYXcgdGhlIG9wZW4gZGV0YWlsIHZpZXdzIGlmIHdlIGNoYW5nZSBjb2x1bW4gcG9zaXRpb24gKGNvbHVtbiByZW9yZGVyKVxyXG4gICAgICAgIHRoaXMuX2V2ZW50SGFuZGxlci5zdWJzY3JpYmUodGhpcy5fZ3JpZC5vbkNvbHVtbnNSZW9yZGVyZWQsIHRoaXMucmVkcmF3QWxsVmlld0NvbXBvbmVudHMuYmluZCh0aGlzKSk7XHJcblxyXG4gICAgICAgIC8vIG9uIHJvdyBzZWxlY3Rpb24gY2hhbmdlZCwgd2UgYWxzbyBuZWVkIHRvIHJlZHJhd1xyXG4gICAgICAgIGlmICh0aGlzLmdyaWRPcHRpb25zLmVuYWJsZVJvd1NlbGVjdGlvbiB8fCB0aGlzLmdyaWRPcHRpb25zLmVuYWJsZUNoZWNrYm94U2VsZWN0b3IpIHtcclxuICAgICAgICAgIHRoaXMuX2V2ZW50SGFuZGxlci5zdWJzY3JpYmUodGhpcy5fZ3JpZC5vblNlbGVjdGVkUm93c0NoYW5nZWQsIHRoaXMucmVkcmF3QWxsVmlld0NvbXBvbmVudHMuYmluZCh0aGlzKSk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAvLyBvbiBzb3J0LCBhbGwgcm93IGRldGFpbCBhcmUgY29sbGFwc2VkIHNvIHdlIGNhbiBkaXNwb3NlIG9mIGFsbCB0aGUgVmlld3MgYXMgd2VsbFxyXG4gICAgICAgIHRoaXMuX2V2ZW50SGFuZGxlci5zdWJzY3JpYmUodGhpcy5fZ3JpZC5vblNvcnQsIHRoaXMuZGlzcG9zZUFsbFZpZXdDb21wb25lbnRzLmJpbmQodGhpcykpO1xyXG5cclxuICAgICAgICAvLyBvbiBmaWx0ZXIgY2hhbmdlZCwgd2UgbmVlZCB0byByZS1yZW5kZXIgYWxsIFZpZXdzXHJcbiAgICAgICAgdGhpcy5fc3Vic2NyaXB0aW9ucy5wdXNoKFxyXG4gICAgICAgICAgdGhpcy5ldmVudFB1YlN1YlNlcnZpY2U/LnN1YnNjcmliZSgnb25GaWx0ZXJDaGFuZ2VkJywgdGhpcy5yZWRyYXdBbGxWaWV3Q29tcG9uZW50cy5iaW5kKHRoaXMpKSxcclxuICAgICAgICAgIHRoaXMuZXZlbnRQdWJTdWJTZXJ2aWNlPy5zdWJzY3JpYmUoJ29uR3JpZE1lbnVDbGVhckFsbEZpbHRlcnMnLCAoKSA9PiBzZXRUaW1lb3V0KCgpID0+IHRoaXMucmVkcmF3QWxsVmlld0NvbXBvbmVudHMoKSkpLFxyXG4gICAgICAgICAgdGhpcy5ldmVudFB1YlN1YlNlcnZpY2U/LnN1YnNjcmliZSgnb25HcmlkTWVudUNsZWFyQWxsU29ydGluZycsICgpID0+IHNldFRpbWVvdXQoKCkgPT4gdGhpcy5yZWRyYXdBbGxWaWV3Q29tcG9uZW50cygpKSksXHJcbiAgICAgICAgKTtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gICAgcmV0dXJuIHRoaXM7XHJcbiAgfVxyXG5cclxuICAvKiogUmVkcmF3IChyZS1yZW5kZXIpIGFsbCB0aGUgZXhwYW5kZWQgcm93IGRldGFpbCBWaWV3IENvbXBvbmVudHMgKi9cclxuICByZWRyYXdBbGxWaWV3Q29tcG9uZW50cygpIHtcclxuICAgIHRoaXMuX3ZpZXdzLmZvckVhY2goKGNvbXBSZWYpID0+IHtcclxuICAgICAgdGhpcy5yZWRyYXdWaWV3Q29tcG9uZW50KGNvbXBSZWYpO1xyXG4gICAgfSk7XHJcbiAgfVxyXG5cclxuICAvKiogUmVuZGVyIGFsbCB0aGUgZXhwYW5kZWQgcm93IGRldGFpbCBWaWV3IENvbXBvbmVudHMgKi9cclxuICByZW5kZXJBbGxWaWV3Q29tcG9uZW50cygpIHtcclxuICAgIHRoaXMuX3ZpZXdzLmZvckVhY2goKHZpZXcpID0+IHtcclxuICAgICAgaWYgKHZpZXcgJiYgdmlldy5kYXRhQ29udGV4dCkge1xyXG4gICAgICAgIHRoaXMucmVuZGVyVmlld01vZGVsKHZpZXcuZGF0YUNvbnRleHQpO1xyXG4gICAgICB9XHJcbiAgICB9KTtcclxuICB9XHJcblxyXG4gIC8qKiBSZWRyYXcgdGhlIG5lY2Vzc2FyeSBWaWV3IENvbXBvbmVudCAqL1xyXG4gIHJlZHJhd1ZpZXdDb21wb25lbnQoY3JlYXRlZFZpZXc6IENyZWF0ZWRWaWV3KSB7XHJcbiAgICBjb25zdCBjb250YWluZXJFbGVtZW50cyA9IHRoaXMuZ3JpZENvbnRhaW5lckVsZW1lbnQuZ2V0RWxlbWVudHNCeUNsYXNzTmFtZShgJHtST1dfREVUQUlMX0NPTlRBSU5FUl9QUkVGSVh9JHtjcmVhdGVkVmlldy5pZH1gKTtcclxuICAgIGlmIChjb250YWluZXJFbGVtZW50cyAmJiBjb250YWluZXJFbGVtZW50cy5sZW5ndGggPj0gMCkge1xyXG4gICAgICB0aGlzLnJlbmRlclZpZXdNb2RlbChjcmVhdGVkVmlldy5kYXRhQ29udGV4dCk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvKiogUmVuZGVyIChvciByZS1yZW5kZXIpIHRoZSBWaWV3IENvbXBvbmVudCAoUm93IERldGFpbCkgKi9cclxuICByZW5kZXJQcmVsb2FkVmlldygpIHtcclxuICAgIGNvbnN0IGNvbnRhaW5lckVsZW1lbnRzID0gdGhpcy5ncmlkQ29udGFpbmVyRWxlbWVudC5nZXRFbGVtZW50c0J5Q2xhc3NOYW1lKGAke1BSRUxPQURfQ09OVEFJTkVSX1BSRUZJWH1gKTtcclxuICAgIGlmIChjb250YWluZXJFbGVtZW50cyAmJiBjb250YWluZXJFbGVtZW50cy5sZW5ndGggPj0gMCkge1xyXG4gICAgICB0aGlzLmFuZ3VsYXJVdGlsU2VydmljZS5jcmVhdGVBbmd1bGFyQ29tcG9uZW50QXBwZW5kVG9Eb20odGhpcy5fcHJlbG9hZENvbXBvbmVudCwgY29udGFpbmVyRWxlbWVudHNbY29udGFpbmVyRWxlbWVudHMubGVuZ3RoIC0gMV0sIHRydWUpO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLyoqIFJlbmRlciAob3IgcmUtcmVuZGVyKSB0aGUgVmlldyBDb21wb25lbnQgKFJvdyBEZXRhaWwpICovXHJcbiAgcmVuZGVyVmlld01vZGVsKGl0ZW06IGFueSk6IENyZWF0ZWRWaWV3IHwgdW5kZWZpbmVkIHtcclxuICAgIGNvbnN0IGNvbnRhaW5lckVsZW1lbnRzID0gdGhpcy5ncmlkQ29udGFpbmVyRWxlbWVudC5nZXRFbGVtZW50c0J5Q2xhc3NOYW1lKGAke1JPV19ERVRBSUxfQ09OVEFJTkVSX1BSRUZJWH0ke2l0ZW1bdGhpcy5kYXRhc2V0SWRQcm9wTmFtZV19YCk7XHJcbiAgICBpZiAoY29udGFpbmVyRWxlbWVudHMgJiYgY29udGFpbmVyRWxlbWVudHMubGVuZ3RoID4gMCkge1xyXG4gICAgICBjb25zdCBjb21wb25lbnRPdXRwdXQgPSB0aGlzLmFuZ3VsYXJVdGlsU2VydmljZS5jcmVhdGVBbmd1bGFyQ29tcG9uZW50QXBwZW5kVG9Eb20odGhpcy5fdmlld0NvbXBvbmVudCwgY29udGFpbmVyRWxlbWVudHNbY29udGFpbmVyRWxlbWVudHMubGVuZ3RoIC0gMV0sIHRydWUpO1xyXG4gICAgICBpZiAoY29tcG9uZW50T3V0cHV0ICYmIGNvbXBvbmVudE91dHB1dC5jb21wb25lbnRSZWYgJiYgY29tcG9uZW50T3V0cHV0LmNvbXBvbmVudFJlZi5pbnN0YW5jZSkge1xyXG4gICAgICAgIC8vIHBhc3MgYSBmZXcgcHJvcGVydGllcyB0byB0aGUgUm93IERldGFpbCB0ZW1wbGF0ZSBjb21wb25lbnRcclxuICAgICAgICBPYmplY3QuYXNzaWduKGNvbXBvbmVudE91dHB1dC5jb21wb25lbnRSZWYuaW5zdGFuY2UsIHtcclxuICAgICAgICAgIG1vZGVsOiBpdGVtLFxyXG4gICAgICAgICAgYWRkb246IHRoaXMsXHJcbiAgICAgICAgICBncmlkOiB0aGlzLl9ncmlkLFxyXG4gICAgICAgICAgZGF0YVZpZXc6IHRoaXMuZGF0YVZpZXcsXHJcbiAgICAgICAgICBwYXJlbnQ6IHRoaXMucm93RGV0YWlsVmlld09wdGlvbnMgJiYgdGhpcy5yb3dEZXRhaWxWaWV3T3B0aW9ucy5wYXJlbnQsXHJcbiAgICAgICAgfSk7XHJcblxyXG4gICAgICAgIGNvbnN0IHZpZXdPYmogPSB0aGlzLl92aWV3cy5maW5kKG9iaiA9PiBvYmouaWQgPT09IGl0ZW1bdGhpcy5kYXRhc2V0SWRQcm9wTmFtZV0pO1xyXG4gICAgICAgIGlmICh2aWV3T2JqKSB7XHJcbiAgICAgICAgICB2aWV3T2JqLmNvbXBvbmVudFJlZiA9IGNvbXBvbmVudE91dHB1dC5jb21wb25lbnRSZWY7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHJldHVybiB2aWV3T2JqO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgICByZXR1cm4gdW5kZWZpbmVkO1xyXG4gIH1cclxuXHJcbiAgLy8gLS1cclxuICAvLyBwcm90ZWN0ZWQgZnVuY3Rpb25zXHJcbiAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tXHJcblxyXG4gIHByb3RlY3RlZCBkaXNwb3NlVmlld0NvbXBvbmVudChleHBhbmRlZFZpZXc6IENyZWF0ZWRWaWV3KTogQ3JlYXRlZFZpZXcgfCB2b2lkIHtcclxuICAgIGNvbnN0IGNvbXBSZWYgPSBleHBhbmRlZFZpZXc/LmNvbXBvbmVudFJlZjtcclxuICAgIGlmIChjb21wUmVmKSB7XHJcbiAgICAgIHRoaXMuYXBwUmVmLmRldGFjaFZpZXcoY29tcFJlZi5ob3N0Vmlldyk7XHJcbiAgICAgIGlmIChjb21wUmVmPy5kZXN0cm95KSB7XHJcbiAgICAgICAgY29tcFJlZi5kZXN0cm95KCk7XHJcbiAgICAgIH1cclxuICAgICAgcmV0dXJuIGV4cGFuZGVkVmlldztcclxuICAgIH1cclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIG5vdGlmeSB0aGUgb25Bc3luY1Jlc3BvbnNlIHdpdGggdGhlIFwiYXJncy5pdGVtXCIgKHJlcXVpcmVkIHByb3BlcnR5KVxyXG4gICAqIHRoZSBwbHVnaW4gd2lsbCB0aGVuIHVzZSBpdGVtIHRvIHBvcHVsYXRlIHRoZSByb3cgZGV0YWlsIHBhbmVsIHdpdGggdGhlIFwicG9zdFRlbXBsYXRlXCJcclxuICAgKiBAcGFyYW0gaXRlbVxyXG4gICAqL1xyXG4gIHByb3RlY3RlZCBub3RpZnlUZW1wbGF0ZShpdGVtOiBhbnkpIHtcclxuICAgIGlmICh0aGlzLm9uQXN5bmNSZXNwb25zZSkge1xyXG4gICAgICB0aGlzLm9uQXN5bmNSZXNwb25zZS5ub3RpZnkoeyBpdGVtIH0sIHVuZGVmaW5lZCwgdGhpcyk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBPbiBQcm9jZXNzaW5nLCB3ZSB3aWxsIG5vdGlmeSB0aGUgcGx1Z2luIHdpdGggdGhlIG5ldyBpdGVtIGRldGFpbCBvbmNlIGJhY2tlbmQgc2VydmVyIGNhbGwgY29tcGxldGVzXHJcbiAgICogQHBhcmFtIGl0ZW1cclxuICAgKi9cclxuICBwcm90ZWN0ZWQgYXN5bmMgb25Qcm9jZXNzaW5nKGl0ZW06IGFueSkge1xyXG4gICAgaWYgKGl0ZW0gJiYgdHlwZW9mIHRoaXMuX3VzZXJQcm9jZXNzRm4gPT09ICdmdW5jdGlvbicpIHtcclxuICAgICAgbGV0IGF3YWl0ZWRJdGVtRGV0YWlsOiBhbnk7XHJcbiAgICAgIGNvbnN0IHVzZXJQcm9jZXNzRm4gPSB0aGlzLl91c2VyUHJvY2Vzc0ZuKGl0ZW0pO1xyXG5cclxuICAgICAgLy8gd2FpdCBmb3IgdGhlIFwidXNlclByb2Nlc3NGblwiLCBvbmNlIHJlc29sdmVkIHdlIHdpbGwgc2F2ZSBpdCBpbnRvIHRoZSBcImNvbGxlY3Rpb25cIlxyXG4gICAgICBjb25zdCByZXNwb25zZTogYW55IHwgYW55W10gPSBhd2FpdCB1c2VyUHJvY2Vzc0ZuO1xyXG5cclxuICAgICAgaWYgKHJlc3BvbnNlLmhhc093blByb3BlcnR5KHRoaXMuZGF0YXNldElkUHJvcE5hbWUpKSB7XHJcbiAgICAgICAgYXdhaXRlZEl0ZW1EZXRhaWwgPSByZXNwb25zZTsgLy8gZnJvbSBQcm9taXNlXHJcbiAgICAgIH0gZWxzZSBpZiAocmVzcG9uc2UgJiYgcmVzcG9uc2UgaW5zdGFuY2VvZiBPYnNlcnZhYmxlIHx8IHJlc3BvbnNlIGluc3RhbmNlb2YgUHJvbWlzZSkge1xyXG4gICAgICAgIGF3YWl0ZWRJdGVtRGV0YWlsID0gYXdhaXQgY2FzdE9ic2VydmFibGVUb1Byb21pc2UodGhpcy5yeGpzIGFzIFJ4SnNGYWNhZGUsIHJlc3BvbnNlKTsgLy8gZnJvbSBBbmd1bGFyLWh0dHAtY2xpZW50XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIGlmICghYXdhaXRlZEl0ZW1EZXRhaWwgfHwgIWF3YWl0ZWRJdGVtRGV0YWlsLmhhc093blByb3BlcnR5KHRoaXMuZGF0YXNldElkUHJvcE5hbWUpKSB7XHJcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBbQW5ndWxhci1TbGlja2dyaWRdIGNvdWxkIG5vdCBwcm9jZXNzIHRoZSBSb3cgRGV0YWlsLCB5b3UgbXVzdCBtYWtlIHN1cmUgdGhhdCB5b3VyIFwicHJvY2Vzc1wiIGNhbGxiYWNrXHJcbiAgICAgICAgICAoYSBQcm9taXNlIG9yIGFuIEh0dHBDbGllbnQgY2FsbCByZXR1cm5pbmcgYW4gT2JzZXJ2YWJsZSkgcmV0dXJucyBhbiBpdGVtIG9iamVjdCB0aGF0IGhhcyBhbiBcIiR7dGhpcy5kYXRhc2V0SWRQcm9wTmFtZX1cIiBwcm9wZXJ0eWApO1xyXG4gICAgICB9XHJcblxyXG4gICAgICAvLyBub3RpZnkgdGhlIHBsdWdpbiB3aXRoIHRoZSBuZXcgaXRlbSBkZXRhaWxzXHJcbiAgICAgIHRoaXMubm90aWZ5VGVtcGxhdGUoYXdhaXRlZEl0ZW1EZXRhaWwgfHwge30pO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogSnVzdCBiZWZvcmUgdGhlIHJvdyBnZXQgZXhwYW5kZWQgb3IgY29sbGFwc2VkIHdlIHdpbGwgZG8gdGhlIGZvbGxvd2luZ1xyXG4gICAqIEZpcnN0IGRldGVybWluZSBpZiB0aGUgcm93IGlzIGV4cGFuZGluZyBvciBjb2xsYXBzaW5nLFxyXG4gICAqIGlmIGl0J3MgZXhwYW5kaW5nIHdlIHdpbGwgYWRkIGl0IHRvIG91ciBWaWV3IENvbXBvbmVudHMgcmVmZXJlbmNlIGFycmF5IGlmIHdlIGRvbid0IGFscmVhZHkgaGF2ZSBpdFxyXG4gICAqIG9yIGlmIGl0J3MgY29sbGFwc2luZyB3ZSB3aWxsIHJlbW92ZSBpdCBmcm9tIG91ciBWaWV3IENvbXBvbmVudHMgcmVmZXJlbmNlIGFycmF5XHJcbiAgICovXHJcbiAgcHJvdGVjdGVkIGhhbmRsZU9uQmVmb3JlUm93RGV0YWlsVG9nZ2xlKGU6IEV2ZW50LCBhcmdzOiB7IGdyaWQ6IFNsaWNrR3JpZDsgaXRlbTogYW55OyB9KSB7XHJcbiAgICAvLyBleHBhbmRpbmdcclxuICAgIGlmIChhcmdzICYmIGFyZ3MuaXRlbSAmJiBhcmdzLml0ZW0uX19jb2xsYXBzZWQpIHtcclxuICAgICAgLy8gZXhwYW5kaW5nIHJvdyBkZXRhaWxcclxuICAgICAgY29uc3Qgdmlld0luZm86IENyZWF0ZWRWaWV3ID0ge1xyXG4gICAgICAgIGlkOiBhcmdzLml0ZW1bdGhpcy5kYXRhc2V0SWRQcm9wTmFtZV0sXHJcbiAgICAgICAgZGF0YUNvbnRleHQ6IGFyZ3MuaXRlbVxyXG4gICAgICB9O1xyXG4gICAgICBjb25zdCBpZFByb3BOYW1lID0gdGhpcy5ncmlkT3B0aW9ucy5kYXRhc2V0SWRQcm9wZXJ0eU5hbWUgfHwgJ2lkJztcclxuICAgICAgYWRkVG9BcnJheVdoZW5Ob3RFeGlzdHModGhpcy5fdmlld3MsIHZpZXdJbmZvLCBpZFByb3BOYW1lKTtcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIC8vIGNvbGxhcHNpbmcsIHNvIGRpc3Bvc2Ugb2YgdGhlIFZpZXcvQ29tcG9uZW50XHJcbiAgICAgIGNvbnN0IGZvdW5kVmlld0luZGV4ID0gdGhpcy5fdmlld3MuZmluZEluZGV4KCh2aWV3OiBDcmVhdGVkVmlldykgPT4gdmlldy5pZCA9PT0gYXJncy5pdGVtW3RoaXMuZGF0YXNldElkUHJvcE5hbWVdKTtcclxuICAgICAgaWYgKGZvdW5kVmlld0luZGV4ID49IDAgJiYgdGhpcy5fdmlld3MuaGFzT3duUHJvcGVydHkoZm91bmRWaWV3SW5kZXgpKSB7XHJcbiAgICAgICAgY29uc3QgY29tcFJlZiA9IHRoaXMuX3ZpZXdzW2ZvdW5kVmlld0luZGV4XS5jb21wb25lbnRSZWY7XHJcbiAgICAgICAgaWYgKGNvbXBSZWYpIHtcclxuICAgICAgICAgIHRoaXMuYXBwUmVmLmRldGFjaFZpZXcoY29tcFJlZi5ob3N0Vmlldyk7XHJcbiAgICAgICAgICBjb21wUmVmLmRlc3Ryb3koKTtcclxuICAgICAgICB9XHJcbiAgICAgICAgdGhpcy5fdmlld3Muc3BsaWNlKGZvdW5kVmlld0luZGV4LCAxKTtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLyoqIFdoZW4gUm93IGNvbWVzIGJhY2sgdG8gVmlld3BvcnQgUmFuZ2UsIHdlIG5lZWQgdG8gcmVkcmF3IHRoZSBWaWV3ICovXHJcbiAgcHJvdGVjdGVkIGhhbmRsZU9uUm93QmFja1RvVmlld3BvcnRSYW5nZShlOiBFdmVudCwgYXJnczogeyBncmlkOiBTbGlja0dyaWQ7IGl0ZW06IGFueTsgcm93SWQ6IG51bWJlcjsgcm93SW5kZXg6IG51bWJlcjsgZXhwYW5kZWRSb3dzOiBhbnlbXTsgcm93SWRzT3V0T2ZWaWV3cG9ydDogbnVtYmVyW107IH0pIHtcclxuICAgIGlmIChhcmdzPy5pdGVtKSB7XHJcbiAgICAgIHRoaXMucmVkcmF3QWxsVmlld0NvbXBvbmVudHMoKTtcclxuICAgIH1cclxuICB9XHJcbn1cclxuIl19