@kepler.gl/reducers 3.3.0-alpha.4 → 3.3.0-alpha.6

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 (71) hide show
  1. package/dist/cjs/combined-updaters.js +491 -0
  2. package/dist/cjs/composer-helpers.js +101 -0
  3. package/dist/cjs/composers.js +22 -0
  4. package/dist/cjs/core.js +105 -0
  5. package/dist/cjs/data-utils.js +53 -0
  6. package/dist/cjs/export-utils.js +91 -0
  7. package/dist/{index.js → cjs/index.js} +1 -1
  8. package/dist/cjs/interaction-utils.js +105 -0
  9. package/dist/cjs/layer-utils.js +635 -0
  10. package/dist/cjs/map-state-updaters.js +654 -0
  11. package/dist/cjs/map-state.js +35 -0
  12. package/dist/cjs/map-style-updaters.js +660 -0
  13. package/dist/cjs/map-style.js +33 -0
  14. package/dist/cjs/merger-handler.js +105 -0
  15. package/dist/cjs/middleware.js +27 -0
  16. package/dist/cjs/provider-state-updaters.js +465 -0
  17. package/dist/cjs/provider-state.js +34 -0
  18. package/dist/cjs/root.js +207 -0
  19. package/dist/cjs/ui-state-updaters.js +905 -0
  20. package/dist/cjs/ui-state.js +36 -0
  21. package/dist/cjs/vis-state-merger.js +1193 -0
  22. package/dist/cjs/vis-state-selectors.js +30 -0
  23. package/dist/cjs/vis-state-updaters.js +4114 -0
  24. package/dist/cjs/vis-state.js +35 -0
  25. package/dist/{combined-updaters.js → esm/combined-updaters.js} +74 -81
  26. package/dist/esm/composer-helpers.js +85 -0
  27. package/dist/esm/composers.js +14 -0
  28. package/dist/esm/core.js +101 -0
  29. package/dist/esm/data-utils.js +47 -0
  30. package/dist/esm/export-utils.js +86 -0
  31. package/dist/esm/index.js +62 -0
  32. package/dist/esm/interaction-utils.js +96 -0
  33. package/dist/esm/layer-utils.js +602 -0
  34. package/dist/esm/map-state-updaters.js +646 -0
  35. package/dist/esm/map-state.js +29 -0
  36. package/dist/esm/map-style-updaters.js +652 -0
  37. package/dist/esm/map-style.js +27 -0
  38. package/dist/esm/merger-handler.js +96 -0
  39. package/dist/esm/middleware.js +19 -0
  40. package/dist/esm/provider-state-updaters.js +458 -0
  41. package/dist/esm/provider-state.js +28 -0
  42. package/dist/esm/root.js +201 -0
  43. package/dist/esm/ui-state-updaters.js +900 -0
  44. package/dist/esm/ui-state.js +30 -0
  45. package/dist/esm/vis-state-merger.js +1161 -0
  46. package/dist/esm/vis-state-selectors.js +24 -0
  47. package/dist/esm/vis-state-updaters.js +4035 -0
  48. package/dist/esm/vis-state.js +29 -0
  49. package/package.json +31 -24
  50. package/dist/composer-helpers.js +0 -101
  51. package/dist/composers.js +0 -22
  52. package/dist/core.js +0 -105
  53. package/dist/data-utils.js +0 -53
  54. package/dist/export-utils.js +0 -91
  55. package/dist/interaction-utils.js +0 -105
  56. package/dist/layer-utils.js +0 -635
  57. package/dist/map-state-updaters.js +0 -649
  58. package/dist/map-state.js +0 -35
  59. package/dist/map-style-updaters.js +0 -660
  60. package/dist/map-style.js +0 -33
  61. package/dist/merger-handler.js +0 -105
  62. package/dist/middleware.js +0 -27
  63. package/dist/provider-state-updaters.js +0 -465
  64. package/dist/provider-state.js +0 -34
  65. package/dist/root.js +0 -207
  66. package/dist/ui-state-updaters.js +0 -905
  67. package/dist/ui-state.js +0 -36
  68. package/dist/vis-state-merger.js +0 -1193
  69. package/dist/vis-state-selectors.js +0 -30
  70. package/dist/vis-state-updaters.js +0 -4114
  71. package/dist/vis-state.js +0 -35
@@ -0,0 +1,646 @@
1
+ import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray";
2
+ import _defineProperty from "@babel/runtime/helpers/esm/defineProperty";
3
+ function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
4
+ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
5
+ // SPDX-License-Identifier: MIT
6
+ // Copyright contributors to the kepler.gl project
7
+
8
+ import geoViewport from '@mapbox/geo-viewport';
9
+ import { booleanWithin } from '@turf/boolean-within';
10
+ import { bboxPolygon } from '@turf/bbox-polygon';
11
+ import { fitBounds } from '@math.gl/web-mercator';
12
+ import deepmerge from 'deepmerge';
13
+ import pick from 'lodash/pick';
14
+ import { getCenterAndZoomFromBounds, validateBounds, MAPBOX_TILE_SIZE, validateViewPort } from '@kepler.gl/utils';
15
+ import { MapSplitMode, MapViewMode, DEFAULT_GLOBE_CONFIG, GLOBE_MIN_ZOOM, GLOBE_MAX_ZOOM, GLOBE_MAX_LATITUDE } from '@kepler.gl/constants';
16
+
17
+ /**
18
+ * Updaters for `mapState` reducer. Can be used in your root reducer to directly modify kepler.gl's state.
19
+ * Read more about [Using updaters](../advanced-usage/using-updaters.md)
20
+ * @public
21
+ * @example
22
+ *
23
+ * import keplerGlReducer, {mapStateUpdaters} from '@kepler.gl/reducers';
24
+ * // Root Reducer
25
+ * const reducers = combineReducers({
26
+ * keplerGl: keplerGlReducer,
27
+ * app: appReducer
28
+ * });
29
+ *
30
+ * const composedReducer = (state, action) => {
31
+ * switch (action.type) {
32
+ * // click button to close side panel
33
+ * case 'CLICK_BUTTON':
34
+ * return {
35
+ * ...state,
36
+ * keplerGl: {
37
+ * ...state.keplerGl,
38
+ * foo: {
39
+ * ...state.keplerGl.foo,
40
+ * mapState: mapStateUpdaters.fitBoundsUpdater(
41
+ * mapState, {payload: [127.34, 31.09, 127.56, 31.59]]}
42
+ * )
43
+ * }
44
+ * }
45
+ * };
46
+ * }
47
+ * return reducers(state, action);
48
+ * };
49
+ *
50
+ * export default composedReducer;
51
+ */
52
+
53
+ /* eslint-disable @typescript-eslint/no-unused-vars */
54
+ // @ts-ignore
55
+ var mapStateUpdaters = null;
56
+ /* eslint-enable @typescript-eslint/no-unused-vars */
57
+ /**
58
+ * Default initial `mapState`
59
+ * @memberof mapStateUpdaters
60
+ * @constant
61
+ * @property pitch Default: `0`
62
+ * @property bearing Default: `0`
63
+ * @property latitude Default: `37.75043`
64
+ * @property longitude Default: `-122.34679`
65
+ * @property zoom Default: `9`
66
+ * @property dragRotate Default: `false`
67
+ * @property width Default: `800`
68
+ * @property height Default: `800`
69
+ * @property minZoom: `undefined`,
70
+ * @property maxZoom: `undefined`,
71
+ * @property maxPitch: `undefined` (defaults to application config value, deck.gl default is 60)
72
+ * @property maxBounds: `undefined`,
73
+ * @property isSplit: `false`,
74
+ * @property isViewportSynced: `true`,
75
+ * @property isZoomLocked: `false`,
76
+ * @property splitMapViewports: `[]`
77
+ * @public
78
+ */
79
+ export var INITIAL_MAP_STATE = {
80
+ pitch: 0,
81
+ bearing: 0,
82
+ latitude: 37.75043,
83
+ longitude: -122.34679,
84
+ zoom: 9,
85
+ dragRotate: false,
86
+ width: 800,
87
+ height: 800,
88
+ minZoom: undefined,
89
+ maxZoom: undefined,
90
+ maxPitch: undefined,
91
+ maxBounds: undefined,
92
+ isSplit: false,
93
+ isViewportSynced: true,
94
+ isZoomLocked: false,
95
+ splitMapViewports: [],
96
+ mapViewMode: MapViewMode.MODE_2D,
97
+ globe: {
98
+ enabled: false,
99
+ config: DEFAULT_GLOBE_CONFIG
100
+ },
101
+ mapSplitMode: MapSplitMode.SINGLE_MAP,
102
+ swipeComparePercentage: 50
103
+ };
104
+
105
+ /* Updaters */
106
+ /**
107
+ * Update map viewport
108
+ * @memberof mapStateUpdaters
109
+ * @public
110
+ */
111
+ export var updateMapUpdater = function updateMapUpdater(state, action) {
112
+ var _action$payload = action.payload,
113
+ inputViewport = _action$payload.viewport,
114
+ _action$payload$mapIn = _action$payload.mapIndex,
115
+ mapIndex = _action$payload$mapIn === void 0 ? 0 : _action$payload$mapIn;
116
+ var viewport = validateViewPort(inputViewport);
117
+ if (state.isViewportSynced) {
118
+ // The `updateViewport` function is typed as (Viewport, Viewport) -> Viewport but here the
119
+ // expected typing is (MapState, Viewport) -> MapState.
120
+ // this could be a potential bug as we treat Viewport and MapState as equal seemingly
121
+ // @ts-expect-error Type 'Viewport' is missing the following properties from type 'MapState': isSplit, isViewportSynced, isZoomLocked, splitMapViewports
122
+ return updateViewport(state, viewport);
123
+ }
124
+ var otherViewportMapIndex = -1;
125
+ var splitMapViewports = state.splitMapViewports.map(function (currentViewport, i) {
126
+ if (i === mapIndex) {
127
+ // update the matching viewport with the newViewport info in the action payload
128
+ return updateViewport(currentViewport, viewport);
129
+ }
130
+ otherViewportMapIndex = i;
131
+ // make no changes to the other viewport (yet)
132
+ return currentViewport;
133
+ });
134
+
135
+ // make conditional updates to the other viewport not matching this payload's `mapIndex`
136
+ if (Number.isFinite(otherViewportMapIndex) && otherViewportMapIndex > -1) {
137
+ // width and height are a special case and are always updated
138
+ splitMapViewports[otherViewportMapIndex] = _objectSpread(_objectSpread({}, splitMapViewports[otherViewportMapIndex]), {}, {
139
+ width: splitMapViewports[mapIndex].width,
140
+ height: splitMapViewports[mapIndex].height
141
+ });
142
+ if (state.isZoomLocked) {
143
+ // update the other viewport with the new zoom from the split viewport that was updated with this payload's `mapIndex`
144
+ splitMapViewports[otherViewportMapIndex] = _objectSpread(_objectSpread({}, splitMapViewports[otherViewportMapIndex]), {}, {
145
+ zoom: splitMapViewports[mapIndex].zoom
146
+ });
147
+ }
148
+ }
149
+ return _objectSpread(_objectSpread(_objectSpread({}, state), splitMapViewports[mapIndex]), {}, {
150
+ // update the mapState with the new array of split viewports
151
+ splitMapViewports: splitMapViewports
152
+ });
153
+ };
154
+
155
+ /**
156
+ * Fit map viewport to bounds
157
+ * @memberof mapStateUpdaters
158
+ * @public
159
+ */
160
+ export var fitBoundsUpdater = function fitBoundsUpdater(state, action) {
161
+ var _state$globe;
162
+ var centerAndZoom = getCenterAndZoomFromBounds(action.payload, {
163
+ width: state.width,
164
+ height: state.height
165
+ });
166
+ if (!centerAndZoom) {
167
+ // bounds is invalid
168
+ return state;
169
+ }
170
+
171
+ // In globe mode, clamp zoom to globe's allowed range
172
+ var isGlobeMode = Boolean((_state$globe = state.globe) === null || _state$globe === void 0 ? void 0 : _state$globe.enabled);
173
+ var zoom = Number.isFinite(centerAndZoom.zoom) ? isGlobeMode ? Math.min(Math.max(centerAndZoom.zoom, GLOBE_MIN_ZOOM), GLOBE_MAX_ZOOM) : centerAndZoom.zoom : undefined;
174
+ var newState = _objectSpread(_objectSpread({}, state), {}, {
175
+ latitude: centerAndZoom.center[1],
176
+ longitude: centerAndZoom.center[0]
177
+ }, zoom !== undefined ? {
178
+ zoom: zoom
179
+ } : {});
180
+
181
+ // if fitting to bounds while split and unsynced
182
+ // copy the new latitude, longitude, and zoom values to each split viewport
183
+ if (newState.splitMapViewports.length) {
184
+ newState.splitMapViewports = newState.splitMapViewports.map(function (currentViewport) {
185
+ return _objectSpread(_objectSpread({}, currentViewport), {}, {
186
+ latitude: newState.latitude,
187
+ longitude: newState.longitude,
188
+ zoom: newState.zoom
189
+ });
190
+ });
191
+ }
192
+ return newState;
193
+ };
194
+
195
+ /**
196
+ * Toggle between 3d and 2d map.
197
+ * @memberof mapStateUpdaters
198
+ * @public
199
+ */
200
+ export var togglePerspectiveUpdater = function togglePerspectiveUpdater(state) {
201
+ var _state$globe2;
202
+ // Only drop min/maxZoom when we're actually leaving globe mode, where those
203
+ // bounds are set to globe-only values. If globe was never enabled these are
204
+ // the app's own custom bounds and must be preserved.
205
+ var wasGlobeEnabled = Boolean((_state$globe2 = state.globe) === null || _state$globe2 === void 0 ? void 0 : _state$globe2.enabled);
206
+ var newState = _objectSpread(_objectSpread(_objectSpread({}, state), {
207
+ pitch: state.dragRotate ? 0 : 50,
208
+ bearing: state.dragRotate ? 0 : 24
209
+ }), {}, {
210
+ dragRotate: !state.dragRotate,
211
+ mapViewMode: state.dragRotate ? MapViewMode.MODE_2D : MapViewMode.MODE_3D,
212
+ globe: _objectSpread(_objectSpread({}, state.globe), {}, {
213
+ enabled: false
214
+ })
215
+ }, wasGlobeEnabled ? {
216
+ minZoom: undefined,
217
+ maxZoom: undefined
218
+ } : {});
219
+
220
+ // if toggling 3d and 2d while split and unsynced
221
+ // copy the new pitch, bearing, and dragRotate values to each split viewport
222
+ if (newState.splitMapViewports.length) {
223
+ newState.splitMapViewports = newState.splitMapViewports.map(function (currentViewport) {
224
+ return _objectSpread(_objectSpread({}, currentViewport), {}, {
225
+ pitch: newState.pitch,
226
+ bearing: newState.bearing,
227
+ dragRotate: newState.dragRotate
228
+ });
229
+ });
230
+ }
231
+ return newState;
232
+ };
233
+
234
+ /**
235
+ * Set map view mode (2D, 3D, Globe)
236
+ * @memberof mapStateUpdaters
237
+ * @public
238
+ */
239
+ export var setMapViewModeUpdater = function setMapViewModeUpdater(state, action) {
240
+ var _state$globe3;
241
+ var mapViewMode = action.payload.mapViewMode;
242
+ var nextState;
243
+
244
+ // Only clear min/maxZoom when leaving globe mode (where they hold globe-only
245
+ // bounds). Otherwise preserve the app's custom bounds.
246
+ var wasGlobeEnabled = Boolean((_state$globe3 = state.globe) === null || _state$globe3 === void 0 ? void 0 : _state$globe3.enabled);
247
+ switch (mapViewMode) {
248
+ case MapViewMode.MODE_2D:
249
+ nextState = _objectSpread(_objectSpread(_objectSpread({}, state), {}, {
250
+ globe: _objectSpread(_objectSpread({}, state.globe), {}, {
251
+ enabled: false
252
+ }),
253
+ pitch: 0,
254
+ bearing: 0,
255
+ dragRotate: false
256
+ }, wasGlobeEnabled ? {
257
+ minZoom: undefined,
258
+ maxZoom: undefined
259
+ } : {}), {}, {
260
+ mapViewMode: mapViewMode
261
+ });
262
+ break;
263
+ case MapViewMode.MODE_3D:
264
+ nextState = _objectSpread(_objectSpread(_objectSpread({}, state), {}, {
265
+ globe: _objectSpread(_objectSpread({}, state.globe), {}, {
266
+ enabled: false
267
+ }),
268
+ pitch: 50,
269
+ bearing: 24,
270
+ dragRotate: true
271
+ }, wasGlobeEnabled ? {
272
+ minZoom: undefined,
273
+ maxZoom: undefined
274
+ } : {}), {}, {
275
+ mapViewMode: mapViewMode
276
+ });
277
+ break;
278
+ case MapViewMode.MODE_GLOBE:
279
+ nextState = _objectSpread(_objectSpread({}, state), {}, {
280
+ globe: _objectSpread(_objectSpread({}, state.globe), {}, {
281
+ enabled: true
282
+ }),
283
+ dragRotate: true,
284
+ pitch: 0,
285
+ bearing: 0,
286
+ // Allow zooming out further than the default so the whole globe can be
287
+ // pulled back on screen. Cap the max zoom so the basemap tiles stay
288
+ // coherent (they break down at high globe zoom in deck.gl 9.x).
289
+ minZoom: GLOBE_MIN_ZOOM,
290
+ maxZoom: GLOBE_MAX_ZOOM,
291
+ zoom: Math.min(Math.max(state.zoom, GLOBE_MIN_ZOOM), GLOBE_MAX_ZOOM),
292
+ mapViewMode: mapViewMode
293
+ });
294
+ break;
295
+ default:
296
+ return state;
297
+ }
298
+ if (nextState.splitMapViewports.length) {
299
+ nextState.splitMapViewports = nextState.splitMapViewports.map(function (currentViewport) {
300
+ return _objectSpread(_objectSpread({}, currentViewport), {}, {
301
+ pitch: nextState.pitch,
302
+ bearing: nextState.bearing,
303
+ dragRotate: nextState.dragRotate
304
+ });
305
+ });
306
+ }
307
+ return nextState;
308
+ };
309
+
310
+ /**
311
+ * Update globe config
312
+ * @memberof mapStateUpdaters
313
+ * @public
314
+ */
315
+ export var globeConfigChangeUpdater = function globeConfigChangeUpdater(state, action) {
316
+ return _objectSpread(_objectSpread({}, state), {}, {
317
+ globe: _objectSpread(_objectSpread({}, state.globe), {}, {
318
+ config: _objectSpread(_objectSpread({}, state.globe.config), action.payload)
319
+ })
320
+ });
321
+ };
322
+
323
+ /**
324
+ * reset mapState to initial State
325
+ * @memberof mapStateUpdaters
326
+ * @public
327
+ */
328
+ export var resetMapConfigUpdater = function resetMapConfigUpdater(state) {
329
+ return _objectSpread(_objectSpread(_objectSpread({}, INITIAL_MAP_STATE), state.initialState), {}, {
330
+ initialState: state.initialState
331
+ });
332
+ };
333
+
334
+ // consider case where you have a split map and user wants to reset
335
+ /**
336
+ * Update `mapState` to propagate a new config
337
+ * @memberof mapStateUpdaters
338
+ * @public
339
+ */
340
+ export var receiveMapConfigUpdater = function receiveMapConfigUpdater(state, _ref) {
341
+ var _ref$payload = _ref.payload,
342
+ _ref$payload$config = _ref$payload.config,
343
+ config = _ref$payload$config === void 0 ? {} : _ref$payload$config,
344
+ _ref$payload$options = _ref$payload.options,
345
+ options = _ref$payload$options === void 0 ? {} : _ref$payload$options,
346
+ _ref$payload$bounds = _ref$payload.bounds,
347
+ bounds = _ref$payload$bounds === void 0 ? null : _ref$payload$bounds;
348
+ /**
349
+ * @type {Partial<MapState>}
350
+ */
351
+ var mapState = (config || {}).mapState || {};
352
+ // merged received mapState with previous state
353
+ // state also may include properties that are new to an existing, saved project's mapState
354
+
355
+ var mergedState = deepmerge(state, mapState, {
356
+ // note: deepmerge by default will merge arrays by concatenating them
357
+ // but we need to overwrite destination arrays with source arrays, if present
358
+ // https://github.com/TehShrike/deepmerge#arraymerge-example-overwrite-target-array
359
+ arrayMerge: function arrayMerge(_destinationArray, sourceArray) {
360
+ return sourceArray;
361
+ }
362
+ });
363
+
364
+ // if center map
365
+ // center map will override mapState config
366
+ if (options.centerMap && bounds) {
367
+ mergedState = fitBoundsUpdater(mergedState, {
368
+ payload: bounds
369
+ });
370
+ }
371
+
372
+ // make sure we validate map state before we merge
373
+ mergedState = validateViewPort(mergedState);
374
+ return _objectSpread(_objectSpread({}, mergedState), getMapDimForSplitMap(mergedState.isSplit, state));
375
+ };
376
+
377
+ /**
378
+ * Toggle between one or split maps
379
+ * @memberof mapStateUpdaters
380
+ * @public
381
+ */
382
+ export var toggleSplitMapUpdater = function toggleSplitMapUpdater(state) {
383
+ return _objectSpread(_objectSpread(_objectSpread({}, state), getMapDimForSplitMap(!state.isSplit, state)), {}, {
384
+ isSplit: !state.isSplit,
385
+ mapSplitMode: !state.isSplit ? MapSplitMode.DUAL_MAP : MapSplitMode.SINGLE_MAP
386
+ }, !state.isSplit === false ? {
387
+ // if toggling to no longer split (single mode) then reset a few properties
388
+ isViewportSynced: true,
389
+ isZoomLocked: false,
390
+ splitMapViewports: []
391
+ } : {});
392
+ };
393
+
394
+ /**
395
+ * Set the map split mode (single, dual, or swipe)
396
+ * @memberof mapStateUpdaters
397
+ * @public
398
+ */
399
+ export var setMapSplitModeUpdater = function setMapSplitModeUpdater(state, action) {
400
+ var mapSplitMode = action.payload.mapSplitMode;
401
+ var prevMode = state.mapSplitMode;
402
+ if (mapSplitMode === prevMode) {
403
+ return state;
404
+ }
405
+ switch (mapSplitMode) {
406
+ case MapSplitMode.SINGLE_MAP:
407
+ return _objectSpread(_objectSpread(_objectSpread({}, state), {}, {
408
+ mapSplitMode: mapSplitMode,
409
+ isSplit: false
410
+ }, prevMode === MapSplitMode.DUAL_MAP && {
411
+ width: state.width * 2
412
+ }), {}, {
413
+ isViewportSynced: true,
414
+ isZoomLocked: false,
415
+ splitMapViewports: []
416
+ });
417
+ case MapSplitMode.DUAL_MAP:
418
+ return _objectSpread(_objectSpread(_objectSpread({}, state), {}, {
419
+ mapSplitMode: mapSplitMode,
420
+ isSplit: true
421
+ }, prevMode === MapSplitMode.SINGLE_MAP && {
422
+ width: state.width / 2
423
+ }), prevMode === MapSplitMode.SWIPE_COMPARE && {
424
+ width: state.width / 2
425
+ });
426
+ case MapSplitMode.SWIPE_COMPARE:
427
+ return _objectSpread(_objectSpread(_objectSpread({}, state), {}, {
428
+ mapSplitMode: mapSplitMode,
429
+ isSplit: true
430
+ }, prevMode === MapSplitMode.DUAL_MAP && {
431
+ width: state.width * 2
432
+ }), {}, {
433
+ isViewportSynced: true,
434
+ isZoomLocked: false,
435
+ splitMapViewports: []
436
+ });
437
+ default:
438
+ return state;
439
+ }
440
+ };
441
+
442
+ /**
443
+ * Set the swipe compare percentage
444
+ * @memberof mapStateUpdaters
445
+ * @public
446
+ */
447
+ export var setSwipeComparePercentageUpdater = function setSwipeComparePercentageUpdater(state, action) {
448
+ var percentage = action.payload.percentage;
449
+ var clamped = Math.min(100, Math.max(0, percentage));
450
+ if (clamped === state.swipeComparePercentage) {
451
+ return state;
452
+ }
453
+ return _objectSpread(_objectSpread({}, state), {}, {
454
+ swipeComparePercentage: clamped
455
+ });
456
+ };
457
+
458
+ /**
459
+ * Toggle between locked and unlocked split viewports
460
+ * @memberof mapStateUpdaters
461
+ * @public
462
+ */
463
+ export var toggleSplitMapViewportUpdater = function toggleSplitMapViewportUpdater(state, action) {
464
+ // Swipe mode always uses synced viewports
465
+ if (state.mapSplitMode === MapSplitMode.SWIPE_COMPARE) {
466
+ return state;
467
+ }
468
+
469
+ // new map state immediately gets the new, optional payload values for isViewportSynced and/or isZoomLocked
470
+ var newMapState = _objectSpread(_objectSpread({}, state), action.payload || {});
471
+ if (newMapState.isViewportSynced) {
472
+ // switching from unsynced to synced viewports
473
+ newMapState.splitMapViewports = [];
474
+ } else {
475
+ // switching from synced to unsynced viewports
476
+ // or already in unsynced mode and toggling locked zoom
477
+
478
+ if (state.isZoomLocked && !newMapState.isZoomLocked) {
479
+ // switching off locked zoom while unsynced
480
+ // don't copy the mapStates to left and right viewports because there will be zoom "jumping"
481
+ return newMapState;
482
+ }
483
+ if (!state.isZoomLocked && newMapState.isZoomLocked) {
484
+ // switching on locked zoom while unsynced
485
+ // only copy zoom viewport property from the most recently interacted-with viewport to the other
486
+ // TODO: do we want to check for a match a different way, such as a combo of `latitude` and `longitude`?
487
+ var lastUpdatedViewportIndex = newMapState.splitMapViewports.findIndex(function (v) {
488
+ return newMapState.zoom === v.zoom;
489
+ });
490
+ var splitMapViewports = newMapState.splitMapViewports.map(function (currentViewport, i) {
491
+ if (i === lastUpdatedViewportIndex) {
492
+ // no zoom to modify here
493
+ return currentViewport;
494
+ }
495
+ // the other viewport gets the most recently interacted-with viewport's zoom
496
+ // WHY? the viewport the user was last interacting with will set zoom across the board for smooth UX
497
+ return _objectSpread(_objectSpread({}, currentViewport), {}, {
498
+ zoom: newMapState.splitMapViewports[lastUpdatedViewportIndex].zoom
499
+ });
500
+ });
501
+ newMapState.splitMapViewports = splitMapViewports;
502
+ return newMapState;
503
+ }
504
+
505
+ // if current viewport is synced, and we are unsyncing it
506
+ // or already in unsynced mode and NOT toggling locked zoom
507
+ // make a fresh copy of the current viewport object, assign it to splitMapViewports[]
508
+ // pickViewportPropsFromMapState is called twice to avoid memory allocation conflicts
509
+ var leftViewport = pickViewportPropsFromMapState(newMapState);
510
+ var rightViewport = pickViewportPropsFromMapState(newMapState);
511
+ newMapState.splitMapViewports = [leftViewport, rightViewport];
512
+ }
513
+
514
+ // return new state
515
+ return newMapState;
516
+ };
517
+
518
+ // Helpers
519
+ export function getMapDimForSplitMap(isSplit, state) {
520
+ // cases:
521
+ // 1. state split: true - isSplit: true
522
+ // do nothing
523
+ // 2. state split: false - isSplit: false
524
+ // do nothing
525
+ if (state.isSplit === isSplit) {
526
+ return {};
527
+ }
528
+
529
+ // In swipe mode, both maps use full width (overlapping with clip)
530
+ if (state.mapSplitMode === MapSplitMode.SWIPE_COMPARE) {
531
+ return {};
532
+ }
533
+ var width = state.isSplit && !isSplit ?
534
+ // 3. state split: true - isSplit: false
535
+ // double width
536
+ state.width * 2 :
537
+ // 4. state split: false - isSplit: true
538
+ // split width
539
+ state.width / 2;
540
+ return {
541
+ width: width
542
+ };
543
+ }
544
+ function updateViewportBasedOnBounds(state, newMapState) {
545
+ // Get the new viewport bounds
546
+ var viewportBounds = geoViewport.bounds([newMapState.longitude, newMapState.latitude], newMapState.zoom, [newMapState.width, newMapState.height], MAPBOX_TILE_SIZE);
547
+ // Generate turf Polygon from bounds for comparison
548
+ var viewportBoundsPolygon = bboxPolygon(viewportBounds);
549
+ // @ts-ignore
550
+ var newStateMaxBounds = newMapState.maxBounds;
551
+ // @ts-ignore
552
+ var maxBoundsPolygon = bboxPolygon(newStateMaxBounds);
553
+
554
+ // If maxBounds has changed reset the viewport to snap to bounds
555
+ var hasMaxBoundsChanged = !state.maxBounds || !state.maxBounds.every(function (val, idx) {
556
+ return val === newStateMaxBounds[idx];
557
+ });
558
+ if (hasMaxBoundsChanged) {
559
+ // Check if the newMapState viewport is within maxBounds
560
+ if (!booleanWithin(viewportBoundsPolygon, maxBoundsPolygon)) {
561
+ var _fitBounds = fitBounds({
562
+ width: newMapState.width,
563
+ height: newMapState.height,
564
+ bounds: [[newStateMaxBounds[0], newStateMaxBounds[1]], [newStateMaxBounds[2], newStateMaxBounds[3]]]
565
+ }),
566
+ latitude = _fitBounds.latitude,
567
+ longitude = _fitBounds.longitude,
568
+ zoom = _fitBounds.zoom;
569
+ newMapState = _objectSpread(_objectSpread({}, newMapState), {}, {
570
+ latitude: latitude,
571
+ longitude: longitude
572
+ }, Number.isFinite(zoom) ? {
573
+ zoom: zoom
574
+ } : {});
575
+ }
576
+ return newMapState;
577
+ }
578
+
579
+ // Check if the newMapState viewport is within maxBounds
580
+ if (!booleanWithin(viewportBoundsPolygon, maxBoundsPolygon)) {
581
+ newMapState = _objectSpread(_objectSpread({}, newMapState), {}, {
582
+ longitude: state.longitude,
583
+ latitude: state.latitude,
584
+ zoom: state.zoom
585
+ });
586
+ }
587
+ return newMapState;
588
+ }
589
+ export function pickViewportPropsFromMapState(state) {
590
+ return pick(state, ['width', 'height', 'zoom', 'pitch', 'bearing', 'latitude', 'longitude', 'dragRotate', 'minZoom', 'maxZoom', 'maxPitch', 'maxBounds']);
591
+ }
592
+
593
+ /** Select items from object whose value is not undefined */
594
+ var definedProps = function definedProps(obj) {
595
+ return Object.entries(obj).reduce(function (accu, _ref2) {
596
+ var _ref3 = _slicedToArray(_ref2, 2),
597
+ k = _ref3[0],
598
+ v = _ref3[1];
599
+ return _objectSpread(_objectSpread({}, accu), v !== undefined ? _defineProperty({}, k, v) : {});
600
+ }, {});
601
+ };
602
+ function updateViewport(originalViewport, viewportUpdates) {
603
+ var _globe;
604
+ var newViewport = _objectSpread(_objectSpread({}, originalViewport), definedProps(viewportUpdates) || {});
605
+
606
+ // deck.gl's globe controller applies a latitude-dependent adjustment to the
607
+ // zoom range (see KeplerGlobeView._constrainZoom). If we clamp the propagated
608
+ // zoom here against the raw minZoom/maxZoom (without that adjustment), Redux
609
+ // ends up disagreeing with the controller: the controller lets the user pull
610
+ // the globe further out, but this clamp snaps zoom back to `minZoom` when the
611
+ // interaction's inertia transition ends. Apply the same adjustment in globe
612
+ // mode so Redux stays consistent with the controller and there's no snap-back.
613
+ var isGlobe = (_globe = newViewport.globe) === null || _globe === void 0 ? void 0 : _globe.enabled;
614
+ if (isGlobe) {
615
+ var _newViewport$latitude;
616
+ // Keep the camera target within a latitude band around the equator so the
617
+ // stored viewport can't be centered on the poles (matches the globe
618
+ // controller's applyConstraints so geocoder/programmatic updates agree).
619
+ if (typeof newViewport.latitude === 'number') {
620
+ newViewport.latitude = Math.min(GLOBE_MAX_LATITUDE, Math.max(-GLOBE_MAX_LATITUDE, newViewport.latitude));
621
+ }
622
+ var zoomAdjustment = Math.log2(Math.cos(((_newViewport$latitude = newViewport.latitude) !== null && _newViewport$latitude !== void 0 ? _newViewport$latitude : 0) * Math.PI / 180));
623
+ if (typeof newViewport.minZoom === 'number' && typeof newViewport.zoom === 'number' && newViewport.zoom < newViewport.minZoom + zoomAdjustment) {
624
+ newViewport.zoom = newViewport.minZoom + zoomAdjustment;
625
+ }
626
+ if (typeof newViewport.maxZoom === 'number' && typeof newViewport.zoom === 'number' && newViewport.zoom > newViewport.maxZoom + zoomAdjustment) {
627
+ newViewport.zoom = newViewport.maxZoom + zoomAdjustment;
628
+ }
629
+ } else {
630
+ // Make sure zoom level doesn't go bellow minZoom if defined
631
+ if (newViewport.minZoom && newViewport.zoom && newViewport.zoom < newViewport.minZoom) {
632
+ newViewport.zoom = newViewport.minZoom;
633
+ }
634
+ // Make sure zoom level doesn't go above maxZoom if defined
635
+ if (newViewport.maxZoom && newViewport.zoom && newViewport.zoom > newViewport.maxZoom) {
636
+ newViewport.zoom = newViewport.maxZoom;
637
+ }
638
+ }
639
+ // Limit viewport update based on maxBounds
640
+ if (newViewport.maxBounds && validateBounds(newViewport.maxBounds)) {
641
+ // @ts-expect-error Type 'Viewport' is missing the following properties from type 'MapState': isSplit, isViewportSynced, isZoomLocked, splitMapViewports
642
+ newViewport = updateViewportBasedOnBounds(originalViewport, newViewport);
643
+ }
644
+ return newViewport;
645
+ }
646
+ //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJnZW9WaWV3cG9ydCIsImJvb2xlYW5XaXRoaW4iLCJiYm94UG9seWdvbiIsImZpdEJvdW5kcyIsImRlZXBtZXJnZSIsInBpY2siLCJnZXRDZW50ZXJBbmRab29tRnJvbUJvdW5kcyIsInZhbGlkYXRlQm91bmRzIiwiTUFQQk9YX1RJTEVfU0laRSIsInZhbGlkYXRlVmlld1BvcnQiLCJNYXBTcGxpdE1vZGUiLCJNYXBWaWV3TW9kZSIsIkRFRkFVTFRfR0xPQkVfQ09ORklHIiwiR0xPQkVfTUlOX1pPT00iLCJHTE9CRV9NQVhfWk9PTSIsIkdMT0JFX01BWF9MQVRJVFVERSIsIm1hcFN0YXRlVXBkYXRlcnMiLCJJTklUSUFMX01BUF9TVEFURSIsInBpdGNoIiwiYmVhcmluZyIsImxhdGl0dWRlIiwibG9uZ2l0dWRlIiwiem9vbSIsImRyYWdSb3RhdGUiLCJ3aWR0aCIsImhlaWdodCIsIm1pblpvb20iLCJ1bmRlZmluZWQiLCJtYXhab29tIiwibWF4UGl0Y2giLCJtYXhCb3VuZHMiLCJpc1NwbGl0IiwiaXNWaWV3cG9ydFN5bmNlZCIsImlzWm9vbUxvY2tlZCIsInNwbGl0TWFwVmlld3BvcnRzIiwibWFwVmlld01vZGUiLCJNT0RFXzJEIiwiZ2xvYmUiLCJlbmFibGVkIiwiY29uZmlnIiwibWFwU3BsaXRNb2RlIiwiU0lOR0xFX01BUCIsInN3aXBlQ29tcGFyZVBlcmNlbnRhZ2UiLCJ1cGRhdGVNYXBVcGRhdGVyIiwic3RhdGUiLCJhY3Rpb24iLCJfYWN0aW9uJHBheWxvYWQiLCJwYXlsb2FkIiwiaW5wdXRWaWV3cG9ydCIsInZpZXdwb3J0IiwiX2FjdGlvbiRwYXlsb2FkJG1hcEluIiwibWFwSW5kZXgiLCJ1cGRhdGVWaWV3cG9ydCIsIm90aGVyVmlld3BvcnRNYXBJbmRleCIsIm1hcCIsImN1cnJlbnRWaWV3cG9ydCIsImkiLCJOdW1iZXIiLCJpc0Zpbml0ZSIsIl9vYmplY3RTcHJlYWQiLCJmaXRCb3VuZHNVcGRhdGVyIiwiX3N0YXRlJGdsb2JlIiwiY2VudGVyQW5kWm9vbSIsImlzR2xvYmVNb2RlIiwiQm9vbGVhbiIsIk1hdGgiLCJtaW4iLCJtYXgiLCJuZXdTdGF0ZSIsImNlbnRlciIsImxlbmd0aCIsInRvZ2dsZVBlcnNwZWN0aXZlVXBkYXRlciIsIl9zdGF0ZSRnbG9iZTIiLCJ3YXNHbG9iZUVuYWJsZWQiLCJNT0RFXzNEIiwic2V0TWFwVmlld01vZGVVcGRhdGVyIiwiX3N0YXRlJGdsb2JlMyIsIm5leHRTdGF0ZSIsIk1PREVfR0xPQkUiLCJnbG9iZUNvbmZpZ0NoYW5nZVVwZGF0ZXIiLCJyZXNldE1hcENvbmZpZ1VwZGF0ZXIiLCJpbml0aWFsU3RhdGUiLCJyZWNlaXZlTWFwQ29uZmlnVXBkYXRlciIsIl9yZWYiLCJfcmVmJHBheWxvYWQiLCJfcmVmJHBheWxvYWQkY29uZmlnIiwiX3JlZiRwYXlsb2FkJG9wdGlvbnMiLCJvcHRpb25zIiwiX3JlZiRwYXlsb2FkJGJvdW5kcyIsImJvdW5kcyIsIm1hcFN0YXRlIiwibWVyZ2VkU3RhdGUiLCJhcnJheU1lcmdlIiwiX2Rlc3RpbmF0aW9uQXJyYXkiLCJzb3VyY2VBcnJheSIsImNlbnRlck1hcCIsImdldE1hcERpbUZvclNwbGl0TWFwIiwidG9nZ2xlU3BsaXRNYXBVcGRhdGVyIiwiRFVBTF9NQVAiLCJzZXRNYXBTcGxpdE1vZGVVcGRhdGVyIiwicHJldk1vZGUiLCJTV0lQRV9DT01QQVJFIiwic2V0U3dpcGVDb21wYXJlUGVyY2VudGFnZVVwZGF0ZXIiLCJwZXJjZW50YWdlIiwiY2xhbXBlZCIsInRvZ2dsZVNwbGl0TWFwVmlld3BvcnRVcGRhdGVyIiwibmV3TWFwU3RhdGUiLCJsYXN0VXBkYXRlZFZpZXdwb3J0SW5kZXgiLCJmaW5kSW5kZXgiLCJ2IiwibGVmdFZpZXdwb3J0IiwicGlja1ZpZXdwb3J0UHJvcHNGcm9tTWFwU3RhdGUiLCJyaWdodFZpZXdwb3J0IiwidXBkYXRlVmlld3BvcnRCYXNlZE9uQm91bmRzIiwidmlld3BvcnRCb3VuZHMiLCJ2aWV3cG9ydEJvdW5kc1BvbHlnb24iLCJuZXdTdGF0ZU1heEJvdW5kcyIsIm1heEJvdW5kc1BvbHlnb24iLCJoYXNNYXhCb3VuZHNDaGFuZ2VkIiwiZXZlcnkiLCJ2YWwiLCJpZHgiLCJfZml0Qm91bmRzIiwiZGVmaW5lZFByb3BzIiwib2JqIiwiT2JqZWN0IiwiZW50cmllcyIsInJlZHVjZSIsImFjY3UiLCJfcmVmMiIsIl9yZWYzIiwiX3NsaWNlZFRvQXJyYXkiLCJrIiwiX2RlZmluZVByb3BlcnR5Iiwib3JpZ2luYWxWaWV3cG9ydCIsInZpZXdwb3J0VXBkYXRlcyIsIl9nbG9iZSIsIm5ld1ZpZXdwb3J0IiwiaXNHbG9iZSIsIl9uZXdWaWV3cG9ydCRsYXRpdHVkZSIsInpvb21BZGp1c3RtZW50IiwibG9nMiIsImNvcyIsIlBJIl0sInNvdXJjZXMiOlsiLi4vLi4vc3JjL21hcC1zdGF0ZS11cGRhdGVycy50cyJdLCJzb3VyY2VzQ29udGVudCI6WyIvLyBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogTUlUXG4vLyBDb3B5cmlnaHQgY29udHJpYnV0b3JzIHRvIHRoZSBrZXBsZXIuZ2wgcHJvamVjdFxuXG5pbXBvcnQgZ2VvVmlld3BvcnQgZnJvbSAnQG1hcGJveC9nZW8tdmlld3BvcnQnO1xuaW1wb3J0IHtib29sZWFuV2l0aGlufSBmcm9tICdAdHVyZi9ib29sZWFuLXdpdGhpbic7XG5pbXBvcnQge2Jib3hQb2x5Z29ufSBmcm9tICdAdHVyZi9iYm94LXBvbHlnb24nO1xuaW1wb3J0IHtmaXRCb3VuZHN9IGZyb20gJ0BtYXRoLmdsL3dlYi1tZXJjYXRvcic7XG5pbXBvcnQgZGVlcG1lcmdlIGZyb20gJ2RlZXBtZXJnZSc7XG5pbXBvcnQgcGljayBmcm9tICdsb2Rhc2gvcGljayc7XG5cbmltcG9ydCB7XG4gIGdldENlbnRlckFuZFpvb21Gcm9tQm91bmRzLFxuICB2YWxpZGF0ZUJvdW5kcyxcbiAgTUFQQk9YX1RJTEVfU0laRSxcbiAgdmFsaWRhdGVWaWV3UG9ydFxufSBmcm9tICdAa2VwbGVyLmdsL3V0aWxzJztcbmltcG9ydCB7TWFwU3RhdGVBY3Rpb25zLCBSZWNlaXZlTWFwQ29uZmlnUGF5bG9hZCwgQWN0aW9uVHlwZXN9IGZyb20gJ0BrZXBsZXIuZ2wvYWN0aW9ucyc7XG5pbXBvcnQge01hcFN0YXRlLCBCb3VuZHMsIFZpZXdwb3J0fSBmcm9tICdAa2VwbGVyLmdsL3R5cGVzJztcbmltcG9ydCB7TWFwU3BsaXRNb2RlLCBNYXBWaWV3TW9kZSwgREVGQVVMVF9HTE9CRV9DT05GSUcsIEdMT0JFX01JTl9aT09NLCBHTE9CRV9NQVhfWk9PTSwgR0xPQkVfTUFYX0xBVElUVURFfSBmcm9tICdAa2VwbGVyLmdsL2NvbnN0YW50cyc7XG5cbi8qKlxuICogVXBkYXRlcnMgZm9yIGBtYXBTdGF0ZWAgcmVkdWNlci4gQ2FuIGJlIHVzZWQgaW4geW91ciByb290IHJlZHVjZXIgdG8gZGlyZWN0bHkgbW9kaWZ5IGtlcGxlci5nbCdzIHN0YXRlLlxuICogUmVhZCBtb3JlIGFib3V0IFtVc2luZyB1cGRhdGVyc10oLi4vYWR2YW5jZWQtdXNhZ2UvdXNpbmctdXBkYXRlcnMubWQpXG4gKiBAcHVibGljXG4gKiBAZXhhbXBsZVxuICpcbiAqIGltcG9ydCBrZXBsZXJHbFJlZHVjZXIsIHttYXBTdGF0ZVVwZGF0ZXJzfSBmcm9tICdAa2VwbGVyLmdsL3JlZHVjZXJzJztcbiAqIC8vIFJvb3QgUmVkdWNlclxuICogY29uc3QgcmVkdWNlcnMgPSBjb21iaW5lUmVkdWNlcnMoe1xuICogIGtlcGxlckdsOiBrZXBsZXJHbFJlZHVjZXIsXG4gKiAgYXBwOiBhcHBSZWR1Y2VyXG4gKiB9KTtcbiAqXG4gKiBjb25zdCBjb21wb3NlZFJlZHVjZXIgPSAoc3RhdGUsIGFjdGlvbikgPT4ge1xuICogIHN3aXRjaCAoYWN0aW9uLnR5cGUpIHtcbiAqICAgIC8vIGNsaWNrIGJ1dHRvbiB0byBjbG9zZSBzaWRlIHBhbmVsXG4gKiAgICBjYXNlICdDTElDS19CVVRUT04nOlxuICogICAgICByZXR1cm4ge1xuICogICAgICAgIC4uLnN0YXRlLFxuICogICAgICAgIGtlcGxlckdsOiB7XG4gKiAgICAgICAgICAuLi5zdGF0ZS5rZXBsZXJHbCxcbiAqICAgICAgICAgIGZvbzoge1xuICogICAgICAgICAgICAgLi4uc3RhdGUua2VwbGVyR2wuZm9vLFxuICogICAgICAgICAgICAgbWFwU3RhdGU6IG1hcFN0YXRlVXBkYXRlcnMuZml0Qm91bmRzVXBkYXRlcihcbiAqICAgICAgICAgICAgICAgbWFwU3RhdGUsIHtwYXlsb2FkOiBbMTI3LjM0LCAzMS4wOSwgMTI3LjU2LCAzMS41OV1dfVxuICogICAgICAgICAgICAgKVxuICogICAgICAgICAgfVxuICogICAgICAgIH1cbiAqICAgICAgfTtcbiAqICB9XG4gKiAgcmV0dXJuIHJlZHVjZXJzKHN0YXRlLCBhY3Rpb24pO1xuICogfTtcbiAqXG4gKiBleHBvcnQgZGVmYXVsdCBjb21wb3NlZFJlZHVjZXI7XG4gKi9cblxuLyogZXNsaW50LWRpc2FibGUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXVudXNlZC12YXJzICovXG4vLyBAdHMtaWdub3JlXG5jb25zdCBtYXBTdGF0ZVVwZGF0ZXJzID0gbnVsbDtcbi8qIGVzbGludC1lbmFibGUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXVudXNlZC12YXJzICovXG4vKipcbiAqIERlZmF1bHQgaW5pdGlhbCBgbWFwU3RhdGVgXG4gKiBAbWVtYmVyb2YgbWFwU3RhdGVVcGRhdGVyc1xuICogQGNvbnN0YW50XG4gKiBAcHJvcGVydHkgcGl0Y2ggRGVmYXVsdDogYDBgXG4gKiBAcHJvcGVydHkgYmVhcmluZyBEZWZhdWx0OiBgMGBcbiAqIEBwcm9wZXJ0eSBsYXRpdHVkZSBEZWZhdWx0OiBgMzcuNzUwNDNgXG4gKiBAcHJvcGVydHkgbG9uZ2l0dWRlIERlZmF1bHQ6IGAtMTIyLjM0Njc5YFxuICogQHByb3BlcnR5IHpvb20gRGVmYXVsdDogYDlgXG4gKiBAcHJvcGVydHkgZHJhZ1JvdGF0ZSBEZWZhdWx0OiBgZmFsc2VgXG4gKiBAcHJvcGVydHkgd2lkdGggRGVmYXVsdDogYDgwMGBcbiAqIEBwcm9wZXJ0eSBoZWlnaHQgRGVmYXVsdDogYDgwMGBcbiAqIEBwcm9wZXJ0eSBtaW5ab29tOiBgdW5kZWZpbmVkYCxcbiAqIEBwcm9wZXJ0eSBtYXhab29tOiBgdW5kZWZpbmVkYCxcbiAqIEBwcm9wZXJ0eSBtYXhQaXRjaDogYHVuZGVmaW5lZGAgKGRlZmF1bHRzIHRvIGFwcGxpY2F0aW9uIGNvbmZpZyB2YWx1ZSwgZGVjay5nbCBkZWZhdWx0IGlzIDYwKVxuICogQHByb3BlcnR5IG1heEJvdW5kczogYHVuZGVmaW5lZGAsXG4gKiBAcHJvcGVydHkgaXNTcGxpdDogYGZhbHNlYCxcbiAqIEBwcm9wZXJ0eSBpc1ZpZXdwb3J0U3luY2VkOiBgdHJ1ZWAsXG4gKiBAcHJvcGVydHkgaXNab29tTG9ja2VkOiBgZmFsc2VgLFxuICogQHByb3BlcnR5IHNwbGl0TWFwVmlld3BvcnRzOiBgW11gXG4gKiBAcHVibGljXG4gKi9cbmV4cG9ydCBjb25zdCBJTklUSUFMX01BUF9TVEFURTogTWFwU3RhdGUgPSB7XG4gIHBpdGNoOiAwLFxuICBiZWFyaW5nOiAwLFxuICBsYXRpdHVkZTogMzcuNzUwNDMsXG4gIGxvbmdpdHVkZTogLTEyMi4zNDY3OSxcbiAgem9vbTogOSxcbiAgZHJhZ1JvdGF0ZTogZmFsc2UsXG4gIHdpZHRoOiA4MDAsXG4gIGhlaWdodDogODAwLFxuICBtaW5ab29tOiB1bmRlZmluZWQsXG4gIG1heFpvb206IHVuZGVmaW5lZCxcbiAgbWF4UGl0Y2g6IHVuZGVmaW5lZCxcbiAgbWF4Qm91bmRzOiB1bmRlZmluZWQsXG4gIGlzU3BsaXQ6IGZhbHNlLFxuICBpc1ZpZXdwb3J0U3luY2VkOiB0cnVlLFxuICBpc1pvb21Mb2NrZWQ6IGZhbHNlLFxuICBzcGxpdE1hcFZpZXdwb3J0czogW10sXG4gIG1hcFZpZXdNb2RlOiBNYXBWaWV3TW9kZS5NT0RFXzJELFxuICBnbG9iZToge1xuICAgIGVuYWJsZWQ6IGZhbHNlLFxuICAgIGNvbmZpZzogREVGQVVMVF9HTE9CRV9DT05GSUdcbiAgfSxcbiAgbWFwU3BsaXRNb2RlOiBNYXBTcGxpdE1vZGUuU0lOR0xFX01BUCxcbiAgc3dpcGVDb21wYXJlUGVyY2VudGFnZTogNTBcbn07XG5cbi8qIFVwZGF0ZXJzICovXG4vKipcbiAqIFVwZGF0ZSBtYXAgdmlld3BvcnRcbiAqIEBtZW1iZXJvZiBtYXBTdGF0ZVVwZGF0ZXJzXG4gKiBAcHVibGljXG4gKi9cbmV4cG9ydCBjb25zdCB1cGRhdGVNYXBVcGRhdGVyID0gKFxuICBzdGF0ZTogTWFwU3RhdGUsXG4gIGFjdGlvbjogTWFwU3RhdGVBY3Rpb25zLlVwZGF0ZU1hcFVwZGF0ZXJBY3Rpb25cbik6IE1hcFN0YXRlID0+IHtcbiAgY29uc3Qge3ZpZXdwb3J0OiBpbnB1dFZpZXdwb3J0LCBtYXBJbmRleCA9IDB9ID0gYWN0aW9uLnBheWxvYWQ7XG4gIGNvbnN0IHZpZXdwb3J0ID0gdmFsaWRhdGVWaWV3UG9ydChpbnB1dFZpZXdwb3J0KTtcblxuICBpZiAoc3RhdGUuaXNWaWV3cG9ydFN5bmNlZCkge1xuICAgIC8vIFRoZSBgdXBkYXRlVmlld3BvcnRgIGZ1bmN0aW9uIGlzIHR5cGVkIGFzIChWaWV3cG9ydCwgVmlld3BvcnQpIC0+IFZpZXdwb3J0IGJ1dCBoZXJlIHRoZVxuICAgIC8vIGV4cGVjdGVkIHR5cGluZyBpcyAoTWFwU3RhdGUsIFZpZXdwb3J0KSAtPiBNYXBTdGF0ZS5cbiAgICAvLyB0aGlzIGNvdWxkIGJlIGEgcG90ZW50aWFsIGJ1ZyBhcyB3ZSB0cmVhdCBWaWV3cG9ydCBhbmQgTWFwU3RhdGUgYXMgZXF1YWwgc2VlbWluZ2x5XG4gICAgLy8gQHRzLWV4cGVjdC1lcnJvciBUeXBlICdWaWV3cG9ydCcgaXMgbWlzc2luZyB0aGUgZm9sbG93aW5nIHByb3BlcnRpZXMgZnJvbSB0eXBlICdNYXBTdGF0ZSc6IGlzU3BsaXQsIGlzVmlld3BvcnRTeW5jZWQsIGlzWm9vbUxvY2tlZCwgc3BsaXRNYXBWaWV3cG9ydHNcbiAgICByZXR1cm4gdXBkYXRlVmlld3BvcnQoc3RhdGUsIHZpZXdwb3J0KTtcbiAgfVxuXG4gIGxldCBvdGhlclZpZXdwb3J0TWFwSW5kZXggPSAtMTtcbiAgY29uc3Qgc3BsaXRNYXBWaWV3cG9ydHMgPSBzdGF0ZS5zcGxpdE1hcFZpZXdwb3J0cy5tYXAoKGN1cnJlbnRWaWV3cG9ydCwgaSkgPT4ge1xuICAgIGlmIChpID09PSBtYXBJbmRleCkge1xuICAgICAgLy8gdXBkYXRlIHRoZSBtYXRjaGluZyB2aWV3cG9ydCB3aXRoIHRoZSBuZXdWaWV3cG9ydCBpbmZvIGluIHRoZSBhY3Rpb24gcGF5bG9hZFxuICAgICAgcmV0dXJuIHVwZGF0ZVZpZXdwb3J0KGN1cnJlbnRWaWV3cG9ydCwgdmlld3BvcnQpO1xuICAgIH1cblxuICAgIG90aGVyVmlld3BvcnRNYXBJbmRleCA9IGk7XG4gICAgLy8gbWFrZSBubyBjaGFuZ2VzIHRvIHRoZSBvdGhlciB2aWV3cG9ydCAoeWV0KVxuICAgIHJldHVybiBjdXJyZW50Vmlld3BvcnQ7XG4gIH0pO1xuXG4gIC8vIG1ha2UgY29uZGl0aW9uYWwgdXBkYXRlcyB0byB0aGUgb3RoZXIgdmlld3BvcnQgbm90IG1hdGNoaW5nIHRoaXMgcGF5bG9hZCdzIGBtYXBJbmRleGBcbiAgaWYgKE51bWJlci5pc0Zpbml0ZShvdGhlclZpZXdwb3J0TWFwSW5kZXgpICYmIG90aGVyVmlld3BvcnRNYXBJbmRleCA+IC0xKSB7XG4gICAgLy8gd2lkdGggYW5kIGhlaWdodCBhcmUgYSBzcGVjaWFsIGNhc2UgYW5kIGFyZSBhbHdheXMgdXBkYXRlZFxuICAgIHNwbGl0TWFwVmlld3BvcnRzW290aGVyVmlld3BvcnRNYXBJbmRleF0gPSB7XG4gICAgICAuLi5zcGxpdE1hcFZpZXdwb3J0c1tvdGhlclZpZXdwb3J0TWFwSW5kZXhdLFxuICAgICAgd2lkdGg6IHNwbGl0TWFwVmlld3BvcnRzW21hcEluZGV4XS53aWR0aCxcbiAgICAgIGhlaWdodDogc3BsaXRNYXBWaWV3cG9ydHNbbWFwSW5kZXhdLmhlaWdodFxuICAgIH07XG5cbiAgICBpZiAoc3RhdGUuaXNab29tTG9ja2VkKSB7XG4gICAgICAvLyB1cGRhdGUgdGhlIG90aGVyIHZpZXdwb3J0IHdpdGggdGhlIG5ldyB6b29tIGZyb20gdGhlIHNwbGl0IHZpZXdwb3J0IHRoYXQgd2FzIHVwZGF0ZWQgd2l0aCB0aGlzIHBheWxvYWQncyBgbWFwSW5kZXhgXG4gICAgICBzcGxpdE1hcFZpZXdwb3J0c1tvdGhlclZpZXdwb3J0TWFwSW5kZXhdID0ge1xuICAgICAgICAuLi5zcGxpdE1hcFZpZXdwb3J0c1tvdGhlclZpZXdwb3J0TWFwSW5kZXhdLFxuICAgICAgICB6b29tOiBzcGxpdE1hcFZpZXdwb3J0c1ttYXBJbmRleF0uem9vbVxuICAgICAgfTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4ge1xuICAgIC8vIHVwZGF0ZSB0aGUgdG9wLWxldmVsIG1hcFN0YXRlIHZpZXdwb3J0IHdpdGggdGhlIG1vc3QgcmVjZW50bHkgaW50ZXJhY3RlZC13aXRoIHNwbGl0IHZpZXdwb3J0XG4gICAgLy8gV0hZPyB0aGlzIGF2b2lkcyB6b29tIGFuZCBib3VuZHMgXCJqdW1waW5nXCIgZHVlIHRvIGEgXCJzdGFsZVwiIHRvcC1sZXZlbCBtYXBTdGF0ZSB2aWV3cG9ydCB3aGVuOlxuICAgIC8vICAxLiB0b2dnbGluZyBvZmYgdGhlIHVuc3luY2VkIHZpZXdwb3J0cyBtb2RlIHRvIHN3aXRjaCB0byB0aGUgc3luY2VkIHZpZXdwb3J0cyBtb2RlXG4gICAgLy8gIDIuIHRvZ2dsaW5nIG9uIHRoZSB6b29tIGxvY2sgZHVyaW5nIGFuIHVuc3luY2VkIHZpZXdwb3J0cyBtb2RlXG4gICAgLi4uc3RhdGUsXG4gICAgLi4uc3BsaXRNYXBWaWV3cG9ydHNbbWFwSW5kZXhdLFxuICAgIC8vIHVwZGF0ZSB0aGUgbWFwU3RhdGUgd2l0aCB0aGUgbmV3IGFycmF5IG9mIHNwbGl0IHZpZXdwb3J0c1xuICAgIHNwbGl0TWFwVmlld3BvcnRzXG4gIH07XG59O1xuXG4vKipcbiAqIEZpdCBtYXAgdmlld3BvcnQgdG8gYm91bmRzXG4gKiBAbWVtYmVyb2YgbWFwU3RhdGVVcGRhdGVyc1xuICogQHB1YmxpY1xuICovXG5leHBvcnQgY29uc3QgZml0Qm91bmRzVXBkYXRlciA9IChcbiAgc3RhdGU6IE1hcFN0YXRlLFxuICBhY3Rpb246IE1hcFN0YXRlQWN0aW9ucy5GaXRCb3VuZHNVcGRhdGVyQWN0aW9uXG4pOiBNYXBTdGF0ZSA9PiB7XG4gIGNvbnN0IGNlbnRlckFuZFpvb20gPSBnZXRDZW50ZXJBbmRab29tRnJvbUJvdW5kcyhhY3Rpb24ucGF5bG9hZCwge1xuICAgIHdpZHRoOiBzdGF0ZS53aWR0aCxcbiAgICBoZWlnaHQ6IHN0YXRlLmhlaWdodFxuICB9KTtcbiAgaWYgKCFjZW50ZXJBbmRab29tKSB7XG4gICAgLy8gYm91bmRzIGlzIGludmFsaWRcbiAgICByZXR1cm4gc3RhdGU7XG4gIH1cblxuICAvLyBJbiBnbG9iZSBtb2RlLCBjbGFtcCB6b29tIHRvIGdsb2JlJ3MgYWxsb3dlZCByYW5nZVxuICBjb25zdCBpc0dsb2JlTW9kZSA9IEJvb2xlYW4oc3RhdGUuZ2xvYmU/LmVuYWJsZWQpO1xuICBjb25zdCB6b29tID0gTnVtYmVyLmlzRmluaXRlKGNlbnRlckFuZFpvb20uem9vbSlcbiAgICA/IGlzR2xvYmVNb2RlXG4gICAgICA/IE1hdGgubWluKE1hdGgubWF4KGNlbnRlckFuZFpvb20uem9vbSwgR0xPQkVfTUlOX1pPT00pLCBHTE9CRV9NQVhfWk9PTSlcbiAgICAgIDogY2VudGVyQW5kWm9vbS56b29tXG4gICAgOiB1bmRlZmluZWQ7XG5cbiAgY29uc3QgbmV3U3RhdGUgPSB7XG4gICAgLi4uc3RhdGUsXG4gICAgbGF0aXR1ZGU6IGNlbnRlckFuZFpvb20uY2VudGVyWzFdLFxuICAgIGxvbmdpdHVkZTogY2VudGVyQW5kWm9vbS5jZW50ZXJbMF0sXG4gICAgLy8gRm9yIG1hcmdpbmFsIG9yIGludmFsaWQgYm91bmRzLCB6b29tIG1heSBiZSBOYU4uIE1ha2Ugc3VyZSB0byBwcm92aWRlIGEgdmFsaWQgdmFsdWUgaW4gb3JkZXJcbiAgICAvLyB0byBhdm9pZCBjb3JydXB0IHN0YXRlIGFuZCBwb3RlbnRpYWwgY3Jhc2hlcyBhcyB6b29tIGlzIGV4cGVjdGVkIHRvIGJlIGEgbnVtYmVyXG4gICAgLi4uKHpvb20gIT09IHVuZGVmaW5lZCA/IHt6b29tfSA6IHt9KVxuICB9O1xuXG4gIC8vIGlmIGZpdHRpbmcgdG8gYm91bmRzIHdoaWxlIHNwbGl0IGFuZCB1bnN5bmNlZFxuICAvLyBjb3B5IHRoZSBuZXcgbGF0aXR1ZGUsIGxvbmdpdHVkZSwgYW5kIHpvb20gdmFsdWVzIHRvIGVhY2ggc3BsaXQgdmlld3BvcnRcbiAgaWYgKG5ld1N0YXRlLnNwbGl0TWFwVmlld3BvcnRzLmxlbmd0aCkge1xuICAgIG5ld1N0YXRlLnNwbGl0TWFwVmlld3BvcnRzID0gbmV3U3RhdGUuc3BsaXRNYXBWaWV3cG9ydHMubWFwKGN1cnJlbnRWaWV3cG9ydCA9PiAoe1xuICAgICAgLi4uY3VycmVudFZpZXdwb3J0LFxuICAgICAgbGF0aXR1ZGU6IG5ld1N0YXRlLmxhdGl0dWRlLFxuICAgICAgbG9uZ2l0dWRlOiBuZXdTdGF0ZS5sb25naXR1ZGUsXG4gICAgICB6b29tOiBuZXdTdGF0ZS56b29tXG4gICAgfSkpO1xuICB9XG5cbiAgcmV0dXJuIG5ld1N0YXRlO1xufTtcblxuLyoqXG4gKiBUb2dnbGUgYmV0d2VlbiAzZCBhbmQgMmQgbWFwLlxuICogQG1lbWJlcm9mIG1hcFN0YXRlVXBkYXRlcnNcbiAqIEBwdWJsaWNcbiAqL1xuZXhwb3J0IGNvbnN0IHRvZ2dsZVBlcnNwZWN0aXZlVXBkYXRlciA9IChzdGF0ZTogTWFwU3RhdGUpOiBNYXBTdGF0ZSA9PiB7XG4gIC8vIE9ubHkgZHJvcCBtaW4vbWF4Wm9vbSB3aGVuIHdlJ3JlIGFjdHVhbGx5IGxlYXZpbmcgZ2xvYmUgbW9kZSwgd2hlcmUgdGhvc2VcbiAgLy8gYm91bmRzIGFyZSBzZXQgdG8gZ2xvYmUtb25seSB2YWx1ZXMuIElmIGdsb2JlIHdhcyBuZXZlciBlbmFibGVkIHRoZXNlIGFyZVxuICAvLyB0aGUgYXBwJ3Mgb3duIGN1c3RvbSBib3VuZHMgYW5kIG11c3QgYmUgcHJlc2VydmVkLlxuICBjb25zdCB3YXNHbG9iZUVuYWJsZWQgPSBCb29sZWFuKHN0YXRlLmdsb2JlPy5lbmFibGVkKTtcblxuICBjb25zdCBuZXdTdGF0ZSA9IHtcbiAgICAuLi5zdGF0ZSxcbiAgICAuLi57XG4gICAgICBwaXRjaDogc3RhdGUuZHJhZ1JvdGF0ZSA/IDAgOiA1MCxcbiAgICAgIGJlYXJpbmc6IHN0YXRlLmRyYWdSb3RhdGUgPyAwIDogMjRcbiAgICB9LFxuICAgIGRyYWdSb3RhdGU6ICFzdGF0ZS5kcmFnUm90YXRlLFxuICAgIG1hcFZpZXdNb2RlOiBzdGF0ZS5kcmFnUm90YXRlID8gTWFwVmlld01vZGUuTU9ERV8yRCA6IE1hcFZpZXdNb2RlLk1PREVfM0QsXG4gICAgZ2xvYmU6IHsuLi5zdGF0ZS5nbG9iZSEsIGVuYWJsZWQ6IGZhbHNlfSxcbiAgICAvLyBMZWF2aW5nIGdsb2JlIG1vZGU6IGRyb3AgZ2xvYmUtb25seSB6b29tIGJvdW5kcyBzbyB0aGUgZmxhdCBtYXAgKGFuZFxuICAgIC8vIGNvbnN1bWVycyBvZiBtYXBTdGF0ZSBzdWNoIGFzIHZpZGVvIGV4cG9ydCkgYXJlbid0IGxlZnQgY2xhbXBlZC4gV2hlblxuICAgIC8vIGdsb2JlIHdhcyBuZXZlciBvbiwga2VlcCB3aGF0ZXZlciBtaW4vbWF4Wm9vbSB0aGUgYXBwIGNvbmZpZ3VyZWQuXG4gICAgLi4uKHdhc0dsb2JlRW5hYmxlZCA/IHttaW5ab29tOiB1bmRlZmluZWQsIG1heFpvb206IHVuZGVmaW5lZH0gOiB7fSlcbiAgfTtcblxuICAvLyBpZiB0b2dnbGluZyAzZCBhbmQgMmQgd2hpbGUgc3BsaXQgYW5kIHVuc3luY2VkXG4gIC8vIGNvcHkgdGhlIG5ldyBwaXRjaCwgYmVhcmluZywgYW5kIGRyYWdSb3RhdGUgdmFsdWVzIHRvIGVhY2ggc3BsaXQgdmlld3BvcnRcbiAgaWYgKG5ld1N0YXRlLnNwbGl0TWFwVmlld3BvcnRzLmxlbmd0aCkge1xuICAgIG5ld1N0YXRlLnNwbGl0TWFwVmlld3BvcnRzID0gbmV3U3RhdGUuc3BsaXRNYXBWaWV3cG9ydHMubWFwKGN1cnJlbnRWaWV3cG9ydCA9PiAoe1xuICAgICAgLi4uY3VycmVudFZpZXdwb3J0LFxuICAgICAgcGl0Y2g6IG5ld1N0YXRlLnBpdGNoLFxuICAgICAgYmVhcmluZzogbmV3U3RhdGUuYmVhcmluZyxcbiAgICAgIGRyYWdSb3RhdGU6IG5ld1N0YXRlLmRyYWdSb3RhdGVcbiAgICB9KSk7XG4gIH1cblxuICByZXR1cm4gbmV3U3RhdGU7XG59O1xuXG4vKipcbiAqIFNldCBtYXAgdmlldyBtb2RlICgyRCwgM0QsIEdsb2JlKVxuICogQG1lbWJlcm9mIG1hcFN0YXRlVXBkYXRlcnNcbiAqIEBwdWJsaWNcbiAqL1xuZXhwb3J0IGNvbnN0IHNldE1hcFZpZXdNb2RlVXBkYXRlciA9IChcbiAgc3RhdGU6IE1hcFN0YXRlLFxuICBhY3Rpb246IE1hcFN0YXRlQWN0aW9ucy5TZXRNYXBWaWV3TW9kZVVwZGF0ZXJBY3Rpb25cbik6IE1hcFN0YXRlID0+IHtcbiAgY29uc3Qge21hcFZpZXdNb2RlfSA9IGFjdGlvbi5wYXlsb2FkO1xuICBsZXQgbmV4dFN0YXRlOiBNYXBTdGF0ZTtcblxuICAvLyBPbmx5IGNsZWFyIG1pbi9tYXhab29tIHdoZW4gbGVhdmluZyBnbG9iZSBtb2RlICh3aGVyZSB0aGV5IGhvbGQgZ2xvYmUtb25seVxuICAvLyBib3VuZHMpLiBPdGhlcndpc2UgcHJlc2VydmUgdGhlIGFwcCdzIGN1c3RvbSBib3VuZHMuXG4gIGNvbnN0IHdhc0dsb2JlRW5hYmxlZCA9IEJvb2xlYW4oc3RhdGUuZ2xvYmU/LmVuYWJsZWQpO1xuXG4gIHN3aXRjaCAobWFwVmlld01vZGUpIHtcbiAgICBjYXNlIE1hcFZpZXdNb2RlLk1PREVfMkQ6XG4gICAgICBuZXh0U3RhdGUgPSB7XG4gICAgICAgIC4uLnN0YXRlLFxuICAgICAgICBnbG9iZTogey4uLnN0YXRlLmdsb2JlISwgZW5hYmxlZDogZmFsc2V9LFxuICAgICAgICBwaXRjaDogMCxcbiAgICAgICAgYmVhcmluZzogMCxcbiAgICAgICAgZHJhZ1JvdGF0ZTogZmFsc2UsXG4gICAgICAgIC8vIENsZWFyIHRoZSBnbG9iZS1vbmx5IHpvb20gYm91bmRzIHNvIHRoZSBmbGF0IG1hcCAoYW5kIGFueXRoaW5nIHRoYXRcbiAgICAgICAgLy8gcmVhZHMgbWFwU3RhdGUsIGUuZy4gdmlkZW8gZXhwb3J0KSBpcyBub3QgbGVmdCB3aXRoIGdsb2JlJ3NcbiAgICAgICAgLy8gbWluL21heFpvb20gYWZ0ZXIgbGVhdmluZyBnbG9iZSBtb2RlLiBPbmx5IHdoZW4gZ2xvYmUgd2FzIGFjdHVhbGx5IG9uLlxuICAgICAgICAuLi4od2FzR2xvYmVFbmFibGVkID8ge21pblpvb206IHVuZGVmaW5lZCwgbWF4Wm9vbTogdW5kZWZpbmVkfSA6IHt9KSxcbiAgICAgICAgbWFwVmlld01vZGVcbiAgICAgIH07XG4gICAgICBicmVhaztcbiAgICBjYXNlIE1hcFZpZXdNb2RlLk1PREVfM0Q6XG4gICAgICBuZXh0U3RhdGUgPSB7XG4gICAgICAgIC4uLnN0YXRlLFxuICAgICAgICBnbG9iZTogey4uLnN0YXRlLmdsb2JlISwgZW5hYmxlZDogZmFsc2V9LFxuICAgICAgICBwaXRjaDogNTAsXG4gICAgICAgIGJlYXJpbmc6IDI0LFxuICAgICAgICBkcmFnUm90YXRlOiB0cnVlLFxuICAgICAgICAuLi4od2FzR2xvYmVFbmFibGVkID8ge21pblpvb206IHVuZGVmaW5lZCwgbWF4Wm9vbTogdW5kZWZpbmVkfSA6IHt9KSxcbiAgICAgICAgbWFwVmlld01vZGVcbiAgICAgIH07XG4gICAgICBicmVhaztcbiAgICBjYXNlIE1hcFZpZXdNb2RlLk1PREVfR0xPQkU6XG4gICAgICBuZXh0U3RhdGUgPSB7XG4gICAgICAgIC4uLnN0YXRlLFxuICAgICAgICBnbG9iZTogey4uLnN0YXRlLmdsb2JlISwgZW5hYmxlZDogdHJ1ZX0sXG4gICAgICAgIGRyYWdSb3RhdGU6IHRydWUsXG4gICAgICAgIHBpdGNoOiAwLFxuICAgICAgICBiZWFyaW5nOiAwLFxuICAgICAgICAvLyBBbGxvdyB6b29taW5nIG91dCBmdXJ0aGVyIHRoYW4gdGhlIGRlZmF1bHQgc28gdGhlIHdob2xlIGdsb2JlIGNhbiBiZVxuICAgICAgICAvLyBwdWxsZWQgYmFjayBvbiBzY3JlZW4uIENhcCB0aGUgbWF4IHpvb20gc28gdGhlIGJhc2VtYXAgdGlsZXMgc3RheVxuICAgICAgICAvLyBjb2hlcmVudCAodGhleSBicmVhayBkb3duIGF0IGhpZ2ggZ2xvYmUgem9vbSBpbiBkZWNrLmdsIDkueCkuXG4gICAgICAgIG1pblpvb206IEdMT0JFX01JTl9aT09NLFxuICAgICAgICBtYXhab29tOiBHTE9CRV9NQVhfWk9PTSxcbiAgICAgICAgem9vbTogTWF0aC5taW4oTWF0aC5tYXgoc3RhdGUuem9vbSwgR0xPQkVfTUlOX1pPT00pLCBHTE9CRV9NQVhfWk9PTSksXG4gICAgICAgIG1hcFZpZXdNb2RlXG4gICAgICB9O1xuICAgICAgYnJlYWs7XG4gICAgZGVmYXVsdDpcbiAgICAgIHJldHVybiBzdGF0ZTtcbiAgfVxuXG4gIGlmIChuZXh0U3RhdGUuc3BsaXRNYXBWaWV3cG9ydHMubGVuZ3RoKSB7XG4gICAgbmV4dFN0YXRlLnNwbGl0TWFwVmlld3BvcnRzID0gbmV4dFN0YXRlLnNwbGl0TWFwVmlld3BvcnRzLm1hcChjdXJyZW50Vmlld3BvcnQgPT4gKHtcbiAgICAgIC4uLmN1cnJlbnRWaWV3cG9ydCxcbiAgICAgIHBpdGNoOiBuZXh0U3RhdGUucGl0Y2gsXG4gICAgICBiZWFyaW5nOiBuZXh0U3RhdGUuYmVhcmluZyxcbiAgICAgIGRyYWdSb3RhdGU6IG5leHRTdGF0ZS5kcmFnUm90YXRlXG4gICAgfSkpO1xuICB9XG5cbiAgcmV0dXJuIG5leHRTdGF0ZTtcbn07XG5cbi8qKlxuICogVXBkYXRlIGdsb2JlIGNvbmZpZ1xuICogQG1lbWJlcm9mIG1hcFN0YXRlVXBkYXRlcnNcbiAqIEBwdWJsaWNcbiAqL1xuZXhwb3J0IGNvbnN0IGdsb2JlQ29uZmlnQ2hhbmdlVXBkYXRlciA9IChcbiAgc3RhdGU6IE1hcFN0YXRlLFxuICBhY3Rpb246IE1hcFN0YXRlQWN0aW9ucy5HbG9iZUNvbmZpZ0NoYW5nZVVwZGF0ZXJBY3Rpb25cbik6IE1hcFN0YXRlID0+IHtcbiAgcmV0dXJuIHtcbiAgICAuLi5zdGF0ZSxcbiAgICBnbG9iZToge1xuICAgICAgLi4uc3RhdGUuZ2xvYmUhLFxuICAgICAgY29uZmlnOiB7XG4gICAgICAgIC4uLnN0YXRlLmdsb2JlIS5jb25maWcsXG4gICAgICAgIC4uLmFjdGlvbi5wYXlsb2FkXG4gICAgICB9XG4gICAgfVxuICB9O1xufTtcblxuLyoqXG4gKiByZXNldCBtYXBTdGF0ZSB0byBpbml0aWFsIFN0YXRlXG4gKiBAbWVtYmVyb2YgbWFwU3RhdGVVcGRhdGVyc1xuICogQHB1YmxpY1xuICovXG5leHBvcnQgY29uc3QgcmVzZXRNYXBDb25maWdVcGRhdGVyID0gKHN0YXRlOiBNYXBTdGF0ZSk6IE1hcFN0YXRlID0+ICh7XG4gIC4uLklOSVRJQUxfTUFQX1NUQVRFLFxuICAuLi5zdGF0ZS5pbml0aWFsU3RhdGUsXG4gIGluaXRpYWxTdGF0ZTogc3RhdGUuaW5pdGlhbFN0YXRlXG59KTtcblxuLy8gY29uc2lkZXIgY2FzZSB3aGVyZSB5b3UgaGF2ZSBhIHNwbGl0IG1hcCBhbmQgdXNlciB3YW50cyB0byByZXNldFxuLyoqXG4gKiBVcGRhdGUgYG1hcFN0YXRlYCB0byBwcm9wYWdhdGUgYSBuZXcgY29uZmlnXG4gKiBAbWVtYmVyb2YgbWFwU3RhdGVVcGRhdGVyc1xuICogQHB1YmxpY1xuICovXG5leHBvcnQgY29uc3QgcmVjZWl2ZU1hcENvbmZpZ1VwZGF0ZXIgPSAoXG4gIHN0YXRlOiBNYXBTdGF0ZSxcbiAge1xuICAgIC8vIEB0cy1leHBlY3QtZXJyb3JcbiAgICBwYXlsb2FkOiB7Y29uZmlnID0ge30sIG9wdGlvbnMgPSB7fSwgYm91bmRzID0gbnVsbH1cbiAgfToge1xuICAgIHR5cGU/OiB0eXBlb2YgQWN0aW9uVHlwZXMuUkVDRUlWRV9NQVBfQ09ORklHO1xuICAgIHBheWxvYWQ6IFJlY2VpdmVNYXBDb25maWdQYXlsb2FkO1xuICB9XG4pOiBNYXBTdGF0ZSA9PiB7XG4gIC8qKlxuICAgKiBAdHlwZSB7UGFydGlhbDxNYXBTdGF0ZT59XG4gICAqL1xuICBjb25zdCBtYXBTdGF0ZSA9IChjb25maWcgfHwge30pLm1hcFN0YXRlIHx8IHt9O1xuICAvLyBtZXJnZWQgcmVjZWl2ZWQgbWFwU3RhdGUgd2l0aCBwcmV2aW91cyBzdGF0ZVxuICAvLyBzdGF0ZSBhbHNvIG1heSBpbmNsdWRlIHByb3BlcnRpZXMgdGhhdCBhcmUgbmV3IHRvIGFuIGV4aXN0aW5nLCBzYXZlZCBwcm9qZWN0J3MgbWFwU3RhdGVcblxuICBsZXQgbWVyZ2VkU3RhdGUgPSBkZWVwbWVyZ2U8TWFwU3RhdGU+KHN0YXRlLCBtYXBTdGF0ZSwge1xuICAgIC8vIG5vdGU6IGRlZXBtZXJnZSBieSBkZWZhdWx0IHdpbGwgbWVyZ2UgYXJyYXlzIGJ5IGNvbmNhdGVuYXRpbmcgdGhlbVxuICAgIC8vIGJ1dCB3ZSBuZWVkIHRvIG92ZXJ3cml0ZSBkZXN0aW5hdGlvbiBhcnJheXMgd2l0aCBzb3VyY2UgYXJyYXlzLCBpZiBwcmVzZW50XG4gICAgLy8gaHR0cHM6Ly9naXRodWIuY29tL1RlaFNocmlrZS9kZWVwbWVyZ2UjYXJyYXltZXJnZS1leGFtcGxlLW92ZXJ3cml0ZS10YXJnZXQtYXJyYXlcbiAgICBhcnJheU1lcmdlOiAoX2Rlc3RpbmF0aW9uQXJyYXksIHNvdXJjZUFycmF5KSA9PiBzb3VyY2VBcnJheVxuICB9KTtcblxuICAvLyBpZiBjZW50ZXIgbWFwXG4gIC8vIGNlbnRlciBtYXAgd2lsbCBvdmVycmlkZSBtYXBTdGF0ZSBjb25maWdcbiAgaWYgKG9wdGlvbnMuY2VudGVyTWFwICYmIGJvdW5kcykge1xuICAgIG1lcmdlZFN0YXRlID0gZml0Qm91bmRzVXBkYXRlcihtZXJnZWRTdGF0ZSwge1xuICAgICAgcGF5bG9hZDogYm91bmRzXG4gICAgfSk7XG4gIH1cblxuICAvLyBtYWtlIHN1cmUgd2UgdmFsaWRhdGUgbWFwIHN0YXRlIGJlZm9yZSB3ZSBtZXJnZVxuICBtZXJnZWRTdGF0ZSA9IHZhbGlkYXRlVmlld1BvcnQobWVyZ2VkU3RhdGUpO1xuXG4gIHJldHVybiB7XG4gICAgLi4ubWVyZ2VkU3RhdGUsXG4gICAgLy8gdXBkYXRlIHdpZHRoIGlmIGBpc1NwbGl0YCBoYXMgY2hhbmdlZFxuICAgIC4uLmdldE1hcERpbUZvclNwbGl0TWFwKG1lcmdlZFN0YXRlLmlzU3BsaXQsIHN0YXRlKVxuICB9O1xufTtcblxuLyoqXG4gKiBUb2dnbGUgYmV0d2VlbiBvbmUgb3Igc3BsaXQgbWFwc1xuICogQG1lbWJlcm9mIG1hcFN0YXRlVXBkYXRlcnNcbiAqIEBwdWJsaWNcbiAqL1xuZXhwb3J0IGNvbnN0IHRvZ2dsZVNwbGl0TWFwVXBkYXRlciA9IChzdGF0ZTogTWFwU3RhdGUpOiBNYXBTdGF0ZSA9PiAoe1xuICAuLi5zdGF0ZSxcbiAgLi4uZ2V0TWFwRGltRm9yU3BsaXRNYXAoIXN0YXRlLmlzU3BsaXQsIHN0YXRlKSxcbiAgaXNTcGxpdDogIXN0YXRlLmlzU3BsaXQsXG4gIG1hcFNwbGl0TW9kZTogIXN0YXRlLmlzU3BsaXQgPyBNYXBTcGxpdE1vZGUuRFVBTF9NQVAgOiBNYXBTcGxpdE1vZGUuU0lOR0xFX01BUCxcbiAgLi4uKCFzdGF0ZS5pc1NwbGl0ID09PSBmYWxzZVxuICAgID8ge1xuICAgICAgICAvLyBpZiB0b2dnbGluZyB0byBubyBsb25nZXIgc3BsaXQgKHNpbmdsZSBtb2RlKSB0aGVuIHJlc2V0IGEgZmV3IHByb3BlcnRpZXNcbiAgICAgICAgaXNWaWV3cG9ydFN5bmNlZDogdHJ1ZSxcbiAgICAgICAgaXNab29tTG9ja2VkOiBmYWxzZSxcbiAgICAgICAgc3BsaXRNYXBWaWV3cG9ydHM6IFtdXG4gICAgICB9XG4gICAgOiB7fSlcbn0pO1xuXG4vKipcbiAqIFNldCB0aGUgbWFwIHNwbGl0IG1vZGUgKHNpbmdsZSwgZHVhbCwgb3Igc3dpcGUpXG4gKiBAbWVtYmVyb2YgbWFwU3RhdGVVcGRhdGVyc1xuICogQHB1YmxpY1xuICovXG5leHBvcnQgY29uc3Qgc2V0TWFwU3BsaXRNb2RlVXBkYXRlciA9IChcbiAgc3RhdGU6IE1hcFN0YXRlLFxuICBhY3Rpb246IE1hcFN0YXRlQWN0aW9ucy5TZXRNYXBTcGxpdE1vZGVVcGRhdGVyQWN0aW9uXG4pOiBNYXBTdGF0ZSA9PiB7XG4gIGNvbnN0IHttYXBTcGxpdE1vZGV9ID0gYWN0aW9uLnBheWxvYWQ7XG4gIGNvbnN0IHByZXZNb2RlID0gc3RhdGUubWFwU3BsaXRNb2RlO1xuXG4gIGlmIChtYXBTcGxpdE1vZGUgPT09IHByZXZNb2RlKSB7XG4gICAgcmV0dXJuIHN0YXRlO1xuICB9XG5cbiAgc3dpdGNoIChtYXBTcGxpdE1vZGUpIHtcbiAgICBjYXNlIE1hcFNwbGl0TW9kZS5TSU5HTEVfTUFQOlxuICAgICAgcmV0dXJuIHtcbiAgICAgICAgLi4uc3RhdGUsXG4gICAgICAgIG1hcFNwbGl0TW9kZSxcbiAgICAgICAgaXNTcGxpdDogZmFsc2UsXG4gICAgICAgIC4uLihwcmV2TW9kZSA9PT0gTWFwU3BsaXRNb2RlLkRVQUxfTUFQICYmIHtcbiAgICAgICAgICB3aWR0aDogc3RhdGUud2lkdGggKiAyXG4gICAgICAgIH0pLFxuICAgICAgICBpc1ZpZXdwb3J0U3luY2VkOiB0cnVlLFxuICAgICAgICBpc1pvb21Mb2NrZWQ6IGZhbHNlLFxuICAgICAgICBzcGxpdE1hcFZpZXdwb3J0czogW11cbiAgICAgIH07XG4gICAgY2FzZSBNYXBTcGxpdE1vZGUuRFVBTF9NQVA6XG4gICAgICByZXR1cm4ge1xuICAgICAgICAuLi5zdGF0ZSxcbiAgICAgICAgbWFwU3BsaXRNb2RlLFxuICAgICAgICBpc1NwbGl0OiB0cnVlLFxuICAgICAgICAuLi4ocHJldk1vZGUgPT09IE1hcFNwbGl0TW9kZS5TSU5HTEVfTUFQICYmIHtcbiAgICAgICAgICB3aWR0aDogc3RhdGUud2lkdGggLyAyXG4gICAgICAgIH0pLFxuICAgICAgICAuLi4ocHJldk1vZGUgPT09IE1hcFNwbGl0TW9kZS5TV0lQRV9DT01QQVJFICYmIHtcbiAgICAgICAgICB3aWR0aDogc3RhdGUud2lkdGggLyAyXG4gICAgICAgIH0pXG4gICAgICB9O1xuICAgIGNhc2UgTWFwU3BsaXRNb2RlLlNXSVBFX0NPTVBBUkU6XG4gICAgICByZXR1cm4ge1xuICAgICAgICAuLi5zdGF0ZSxcbiAgICAgICAgbWFwU3BsaXRNb2RlLFxuICAgICAgICBpc1NwbGl0OiB0cnVlLFxuICAgICAgICAuLi4ocHJldk1vZGUgPT09IE1hcFNwbGl0TW9kZS5EVUFMX01BUCAmJiB7XG4gICAgICAgICAgd2lkdGg6IHN0YXRlLndpZHRoICogMlxuICAgICAgICB9KSxcbiAgICAgICAgaXNWaWV3cG9ydFN5bmNlZDogdHJ1ZSxcbiAgICAgICAgaXNab29tTG9ja2VkOiBmYWxzZSxcbiAgICAgICAgc3BsaXRNYXBWaWV3cG9ydHM6IFtdXG4gICAgICB9O1xuICAgIGRlZmF1bHQ6XG4gICAgICByZXR1cm4gc3RhdGU7XG4gIH1cbn07XG5cbi8qKlxuICogU2V0IHRoZSBzd2lwZSBjb21wYXJlIHBlcmNlbnRhZ2VcbiAqIEBtZW1iZXJvZiBtYXBTdGF0ZVVwZGF0ZXJzXG4gKiBAcHVibGljXG4gKi9cbmV4cG9ydCBjb25zdCBzZXRTd2lwZUNvbXBhcmVQZXJjZW50YWdlVXBkYXRlciA9IChcbiAgc3RhdGU6IE1hcFN0YXRlLFxuICBhY3Rpb246IE1hcFN0YXRlQWN0aW9ucy5TZXRTd2lwZUNvbXBhcmVQZXJjZW50YWdlVXBkYXRlckFjdGlvblxuKTogTWFwU3RhdGUgPT4ge1xuICBjb25zdCB7cGVyY2VudGFnZX0gPSBhY3Rpb24ucGF5bG9hZDtcbiAgY29uc3QgY2xhbXBlZCA9IE1hdGgubWluKDEwMCwgTWF0aC5tYXgoMCwgcGVyY2VudGFnZSkpO1xuICBpZiAoY2xhbXBlZCA9PT0gc3RhdGUuc3dpcGVDb21wYXJlUGVyY2VudGFnZSkge1xuICAgIHJldHVybiBzdGF0ZTtcbiAgfVxuICByZXR1cm4ge1xuICAgIC4uLnN0YXRlLFxuICAgIHN3aXBlQ29tcGFyZVBlcmNlbnRhZ2U6IGNsYW1wZWRcbiAgfTtcbn07XG5cbi8qKlxuICogVG9nZ2xlIGJldHdlZW4gbG9ja2VkIGFuZCB1bmxvY2tlZCBzcGxpdCB2aWV3cG9ydHNcbiAqIEBtZW1iZXJvZiBtYXBTdGF0ZVVwZGF0ZXJzXG4gKiBAcHVibGljXG4gKi9cbmV4cG9ydCBjb25zdCB0b2dnbGVTcGxpdE1hcFZpZXdwb3J0VXBkYXRlciA9IChcbiAgc3RhdGU6IE1hcFN0YXRlLFxuICBhY3Rpb246IE1hcFN0YXRlQWN0aW9ucy5Ub2dnbGVTcGxpdE1hcFZpZXdwb3J0VXBkYXRlckFjdGlvblxuKSA9PiB7XG4gIC8vIFN3aXBlIG1vZGUgYWx3YXlzIHVzZXMgc3luY2VkIHZpZXdwb3J0c1xuICBpZiAoc3RhdGUubWFwU3BsaXRNb2RlID09PSBNYXBTcGxpdE1vZGUuU1dJUEVfQ09NUEFSRSkge1xuICAgIHJldHVybiBzdGF0ZTtcbiAgfVxuXG4gIC8vIG5ldyBtYXAgc3RhdGUgaW1tZWRpYXRlbHkgZ2V0cyB0aGUgbmV3LCBvcHRpb25hbCBwYXlsb2FkIHZhbHVlcyBmb3IgaXNWaWV3cG9ydFN5bmNlZCBhbmQvb3IgaXNab29tTG9ja2VkXG4gIGNvbnN0IG5ld01hcFN0YXRlID0ge1xuICAgIC4uLnN0YXRlLFxuICAgIC4uLihhY3Rpb24ucGF5bG9hZCB8fCB7fSlcbiAgfTtcblxuICBpZiAobmV3TWFwU3RhdGUuaXNWaWV3cG9ydFN5bmNlZCkge1xuICAgIC8vIHN3aXRjaGluZyBmcm9tIHVuc3luY2VkIHRvIHN5bmNlZCB2aWV3cG9ydHNcbiAgICBuZXdNYXBTdGF0ZS5zcGxpdE1hcFZpZXdwb3J0cyA9IFtdO1xuICB9IGVsc2Uge1xuICAgIC8vIHN3aXRjaGluZyBmcm9tIHN5bmNlZCB0byB1bnN5bmNlZCB2aWV3cG9ydHNcbiAgICAvLyBvciBhbHJlYWR5IGluIHVuc3luY2VkIG1vZGUgYW5kIHRvZ2dsaW5nIGxvY2tlZCB6b29tXG5cbiAgICBpZiAoc3RhdGUuaXNab29tTG9ja2VkICYmICFuZXdNYXBTdGF0ZS5pc1pvb21Mb2NrZWQpIHtcbiAgICAgIC8vIHN3aXRjaGluZyBvZmYgbG9ja2VkIHpvb20gd2hpbGUgdW5zeW5jZWRcbiAgICAgIC8vIGRvbid0IGNvcHkgdGhlIG1hcFN0YXRlcyB0byBsZWZ0IGFuZCByaWdodCB2aWV3cG9ydHMgYmVjYXVzZSB0aGVyZSB3aWxsIGJlIHpvb20gXCJqdW1waW5nXCJcbiAgICAgIHJldHVybiBuZXdNYXBTdGF0ZTtcbiAgICB9XG5cbiAgICBpZiAoIXN0YXRlLmlzWm9vbUxvY2tlZCAmJiBuZXdNYXBTdGF0ZS5pc1pvb21Mb2NrZWQpIHtcbiAgICAgIC8vIHN3aXRjaGluZyBvbiBsb2NrZWQgem9vbSB3aGlsZSB1bnN5bmNlZFxuICAgICAgLy8gb25seSBjb3B5IHpvb20gdmlld3BvcnQgcHJvcGVydHkgZnJvbSB0aGUgbW9zdCByZWNlbnRseSBpbnRlcmFjdGVkLXdpdGggdmlld3BvcnQgdG8gdGhlIG90aGVyXG4gICAgICAvLyBUT0RPOiBkbyB3ZSB3YW50IHRvIGNoZWNrIGZvciBhIG1hdGNoIGEgZGlmZmVyZW50IHdheSwgc3VjaCBhcyBhIGNvbWJvIG9mIGBsYXRpdHVkZWAgYW5kIGBsb25naXR1ZGVgP1xuICAgICAgY29uc3QgbGFzdFVwZGF0ZWRWaWV3cG9ydEluZGV4ID0gbmV3TWFwU3RhdGUuc3BsaXRNYXBWaWV3cG9ydHMuZmluZEluZGV4KFxuICAgICAgICB2ID0+IG5ld01hcFN0YXRlLnpvb20gPT09IHYuem9vbVxuICAgICAgKTtcblxuICAgICAgY29uc3Qgc3BsaXRNYXBWaWV3cG9ydHMgPSBuZXdNYXBTdGF0ZS5zcGxpdE1hcFZpZXdwb3J0cy5tYXAoKGN1cnJlbnRWaWV3cG9ydCwgaSkgPT4ge1xuICAgICAgICBpZiAoaSA9PT0gbGFzdFVwZGF0ZWRWaWV3cG9ydEluZGV4KSB7XG4gICAgICAgICAgLy8gbm8gem9vbSB0byBtb2RpZnkgaGVyZVxuICAgICAgICAgIHJldHVybiBjdXJyZW50Vmlld3BvcnQ7XG4gICAgICAgIH1cbiAgICAgICAgLy8gdGhlIG90aGVyIHZpZXdwb3J0IGdldHMgdGhlIG1vc3QgcmVjZW50bHkgaW50ZXJhY3RlZC13aXRoIHZpZXdwb3J0J3Mgem9vbVxuICAgICAgICAvLyBXSFk/IHRoZSB2aWV3cG9ydCB0aGUgdXNlciB3YXMgbGFzdCBpbnRlcmFjdGluZyB3aXRoIHdpbGwgc2V0IHpvb20gYWNyb3NzIHRoZSBib2FyZCBmb3Igc21vb3RoIFVYXG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgLi4uY3VycmVudFZpZXdwb3J0LFxuICAgICAgICAgIHpvb206IG5ld01hcFN0YXRlLnNwbGl0TWFwVmlld3BvcnRzW2xhc3RVcGRhdGVkVmlld3BvcnRJbmRleF0uem9vbVxuICAgICAgICB9O1xuICAgICAgfSk7XG5cbiAgICAgIG5ld01hcFN0YXRlLnNwbGl0TWFwVmlld3BvcnRzID0gc3BsaXRNYXBWaWV3cG9ydHM7XG5cbiAgICAgIHJldHVybiBuZXdNYXBTdGF0ZTtcbiAgICB9XG5cbiAgICAvLyBpZiBjdXJyZW50IHZpZXdwb3J0IGlzIHN5bmNlZCwgYW5kIHdlIGFyZSB1bnN5bmNpbmcgaXRcbiAgICAvLyBvciBhbHJlYWR5IGluIHVuc3luY2VkIG1vZGUgYW5kIE5PVCB0b2dnbGluZyBsb2NrZWQgem9vbVxuICAgIC8vIG1ha2UgYSBmcmVzaCBjb3B5IG9mIHRoZSBjdXJyZW50IHZpZXdwb3J0IG9iamVjdCwgYXNzaWduIGl0IHRvIHNwbGl0TWFwVmlld3BvcnRzW11cbiAgICAvLyBwaWNrVmlld3BvcnRQcm9wc0Zyb21NYXBTdGF0ZSBpcyBjYWxsZWQgdHdpY2UgdG8gYXZvaWQgbWVtb3J5IGFsbG9jYXRpb24gY29uZmxpY3RzXG4gICAgY29uc3QgbGVmdFZpZXdwb3J0ID0gcGlja1ZpZXdwb3J0UHJvcHNGcm9tTWFwU3RhdGUobmV3TWFwU3RhdGUpO1xuICAgIGNvbnN0IHJpZ2h0Vmlld3BvcnQgPSBwaWNrVmlld3BvcnRQcm9wc0Zyb21NYXBTdGF0ZShuZXdNYXBTdGF0ZSk7XG4gICAgbmV3TWFwU3RhdGUuc3BsaXRNYXBWaWV3cG9ydHMgPSBbbGVmdFZpZXdwb3J0LCByaWdodFZpZXdwb3J0XTtcbiAgfVxuXG4gIC8vIHJldHVybiBuZXcgc3RhdGVcbiAgcmV0dXJuIG5ld01hcFN0YXRlO1xufTtcblxuLy8gSGVscGVyc1xuZXhwb3J0IGZ1bmN0aW9uIGdldE1hcERpbUZvclNwbGl0TWFwKGlzU3BsaXQsIHN0YXRlKSB7XG4gIC8vIGNhc2VzOlxuICAvLyAxLiBzdGF0ZSBzcGxpdDogdHJ1ZSAtIGlzU3BsaXQ6IHRydWVcbiAgLy8gZG8gbm90aGluZ1xuICAvLyAyLiBzdGF0ZSBzcGxpdDogZmFsc2UgLSBpc1NwbGl0OiBmYWxzZVxuICAvLyBkbyBub3RoaW5nXG4gIGlmIChzdGF0ZS5pc1NwbGl0ID09PSBpc1NwbGl0KSB7XG4gICAgcmV0dXJuIHt9O1xuICB9XG5cbiAgLy8gSW4gc3dpcGUgbW9kZSwgYm90aCBtYXBzIHVzZSBmdWxsIHdpZHRoIChvdmVybGFwcGluZyB3aXRoIGNsaXApXG4gIGlmIChzdGF0ZS5tYXBTcGxpdE1vZGUgPT09IE1hcFNwbGl0TW9kZS5TV0lQRV9DT01QQVJFKSB7XG4gICAgcmV0dXJuIHt9O1xuICB9XG5cbiAgY29uc3Qgd2lkdGggPVxuICAgIHN0YXRlLmlzU3BsaXQgJiYgIWlzU3BsaXRcbiAgICAgID8gLy8gMy4gc3RhdGUgc3BsaXQ6IHRydWUgLSBpc1NwbGl0OiBmYWxzZVxuICAgICAgICAvLyBkb3VibGUgd2lkdGhcbiAgICAgICAgc3RhdGUud2lkdGggKiAyXG4gICAgICA6IC8vIDQuIHN0YXRlIHNwbGl0OiBmYWxzZSAtIGlzU3BsaXQ6IHRydWVcbiAgICAgICAgLy8gc3BsaXQgd2lkdGhcbiAgICAgICAgc3RhdGUud2lkdGggLyAyO1xuXG4gIHJldHVybiB7XG4gICAgd2lkdGhcbiAgfTtcbn1cblxuZnVuY3Rpb24gdXBkYXRlVmlld3BvcnRCYXNlZE9uQm91bmRzKHN0YXRlOiBNYXBTdGF0ZSwgbmV3TWFwU3RhdGU6IE1hcFN0YXRlKSB7XG4gIC8vIEdldCB0aGUgbmV3IHZpZXdwb3J0IGJvdW5kc1xuICBjb25zdCB2aWV3cG9ydEJvdW5kcyA9IGdlb1ZpZXdwb3J0LmJvdW5kcyhcbiAgICBbbmV3TWFwU3RhdGUubG9uZ2l0dWRlLCBuZXdNYXBTdGF0ZS5sYXRpdHVkZV0sXG4gICAgbmV3TWFwU3RhdGUuem9vbSxcbiAgICBbbmV3TWFwU3RhdGUud2lkdGgsIG5ld01hcFN0YXRlLmhlaWdodF0sXG4gICAgTUFQQk9YX1RJTEVfU0laRVxuICApO1xuICAvLyBHZW5lcmF0ZSB0dXJmIFBvbHlnb24gZnJvbSBib3VuZHMgZm9yIGNvbXBhcmlzb25cbiAgY29uc3Qgdmlld3BvcnRCb3VuZHNQb2x5Z29uID0gYmJveFBvbHlnb24odmlld3BvcnRCb3VuZHMpO1xuICAvLyBAdHMtaWdub3JlXG4gIGNvbnN0IG5ld1N0YXRlTWF4Qm91bmRzOiBCb3VuZHMgPSBuZXdNYXBTdGF0ZS5tYXhCb3VuZHM7XG4gIC8vIEB0cy1pZ25vcmVcbiAgY29uc3QgbWF4Qm91bmRzUG9seWdvbiA9IGJib3hQb2x5Z29uKG5ld1N0YXRlTWF4Qm91bmRzKTtcblxuICAvLyBJZiBtYXhCb3VuZHMgaGFzIGNoYW5nZWQgcmVzZXQgdGhlIHZpZXdwb3J0IHRvIHNuYXAgdG8gYm91bmRzXG4gIGNvbnN0IGhhc01heEJvdW5kc0NoYW5nZWQgPVxuICAgICFzdGF0ZS5tYXhCb3VuZHMgfHwgIXN0YXRlLm1heEJvdW5kcy5ldmVyeSgodmFsLCBpZHgpID0+IHZhbCA9PT0gbmV3U3RhdGVNYXhCb3VuZHNbaWR4XSk7XG4gIGlmIChoYXNNYXhCb3VuZHNDaGFuZ2VkKSB7XG4gICAgLy8gQ2hlY2sgaWYgdGhlIG5ld01hcFN0YXRlIHZpZXdwb3J0IGlzIHdpdGhpbiBtYXhCb3VuZHNcbiAgICBpZiAoIWJvb2xlYW5XaXRoaW4odmlld3BvcnRCb3VuZHNQb2x5Z29uLCBtYXhCb3VuZHNQb2x5Z29uKSkge1xuICAgICAgY29uc3Qge2xhdGl0dWRlLCBsb25naXR1ZGUsIHpvb219ID0gZml0Qm91bmRzKHtcbiAgICAgICAgd2lkdGg6IG5ld01hcFN0YXRlLndpZHRoLFxuICAgICAgICBoZWlnaHQ6IG5ld01hcFN0YXRlLmhlaWdodCxcbiAgICAgICAgYm91bmRzOiBbXG4gICAgICAgICAgW25ld1N0YXRlTWF4Qm91bmRzWzBdLCBuZXdTdGF0ZU1heEJvdW5kc1sxXV0sXG4gICAgICAgICAgW25ld1N0YXRlTWF4Qm91bmRzWzJdLCBuZXdTdGF0ZU1heEJvdW5kc1szXV1cbiAgICAgICAgXVxuICAgICAgfSk7XG5cbiAgICAgIG5ld01hcFN0YXRlID0ge1xuICAgICAgICAuLi5uZXdNYXBTdGF0ZSxcbiAgICAgICAgbGF0aXR1ZGUsXG4gICAgICAgIGxvbmdpdHVkZSxcbiAgICAgICAgLy8gRm9yIG1hcmdpbmFsIG9yIGludmFsaWQgYm91bmRzLCB6b29tIG1heSBiZSBOYU4uIE1ha2Ugc3VyZSB0byBwcm92aWRlIGEgdmFsaWQgdmFsdWUgaW4gb3JkZXJcbiAgICAgICAgLy8gdG8gYXZvaWQgY29ycnVwdCBzdGF0ZSBhbmQgcG90ZW50aWFsIGNyYXNoZXMgYXMgem9vbSBpcyBleHBlY3RlZCB0byBiZSBhIG51bWJlclxuICAgICAgICAuLi4oTnVtYmVyLmlzRmluaXRlKHpvb20pID8ge3pvb219IDoge30pXG4gICAgICB9O1xuICAgIH1cbiAgICByZXR1cm4gbmV3TWFwU3RhdGU7XG4gIH1cblxuICAvLyBDaGVjayBpZiB0aGUgbmV3TWFwU3RhdGUgdmlld3BvcnQgaXMgd2l0aGluIG1heEJvdW5kc1xuICBpZiAoIWJvb2xlYW5XaXRoaW4odmlld3BvcnRCb3VuZHNQb2x5Z29uLCBtYXhCb3VuZHNQb2x5Z29uKSkge1xuICAgIG5ld01hcFN0YXRlID0ge1xuICAgICAgLi4ubmV3TWFwU3RhdGUsXG4gICAgICBsb25naXR1ZGU6IHN0YXRlLmxvbmdpdHVkZSxcbiAgICAgIGxhdGl0dWRlOiBzdGF0ZS5sYXRpdHVkZSxcbiAgICAgIHpvb206IHN0YXRlLnpvb21cbiAgICB9O1xuICB9XG5cbiAgcmV0dXJuIG5ld01hcFN0YXRlO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gcGlja1ZpZXdwb3J0UHJvcHNGcm9tTWFwU3RhdGUoc3RhdGU6IE1hcFN0YXRlKTogVmlld3BvcnQge1xuICByZXR1cm4gcGljayhzdGF0ZSwgW1xuICAgICd3aWR0aCcsXG4gICAgJ2hlaWdodCcsXG4gICAgJ3pvb20nLFxuICAgICdwaXRjaCcsXG4gICAgJ2JlYXJpbmcnLFxuICAgICdsYXRpdHVkZScsXG4gICAgJ2xvbmdpdHVkZScsXG4gICAgJ2RyYWdSb3RhdGUnLFxuICAgICdtaW5ab29tJyxcbiAgICAnbWF4Wm9vbScsXG4gICAgJ21heFBpdGNoJyxcbiAgICAnbWF4Qm91bmRzJ1xuICBdKTtcbn1cblxuLyoqIFNlbGVjdCBpdGVtcyBmcm9tIG9iamVjdCB3aG9zZSB2YWx1ZSBpcyBub3QgdW5kZWZpbmVkICovXG5jb25zdCBkZWZpbmVkUHJvcHMgPSBvYmogPT5cbiAgT2JqZWN0LmVudHJpZXMob2JqKS5yZWR1Y2UoXG4gICAgKGFjY3UsIFtrLCB2XSkgPT4gKHsuLi5hY2N1LCAuLi4odiAhPT0gdW5kZWZpbmVkID8ge1trXTogdn0gOiB7fSl9KSxcbiAgICB7fVxuICApO1xuXG5mdW5jdGlvbiB1cGRhdGVWaWV3cG9ydChvcmlnaW5hbFZpZXdwb3J0OiBWaWV3cG9ydCwgdmlld3BvcnRVcGRhdGVzOiBWaWV3cG9ydCk6IFZpZXdwb3J0IHtcbiAgbGV0IG5ld1ZpZXdwb3J0ID0ge1xuICAgIC4uLm9yaWdpbmFsVmlld3BvcnQsXG4gICAgLi4uKGRlZmluZWRQcm9wcyh2aWV3cG9ydFVwZGF0ZXMpIHx8IHt9KVxuICB9O1xuXG4gIC8vIGRlY2suZ2wncyBnbG9iZSBjb250cm9sbGVyIGFwcGxpZXMgYSBsYXRpdHVkZS1kZXBlbmRlbnQgYWRqdXN0bWVudCB0byB0aGVcbiAgLy8gem9vbSByYW5nZSAoc2VlIEtlcGxlckdsb2JlVmlldy5fY29uc3RyYWluWm9vbSkuIElmIHdlIGNsYW1wIHRoZSBwcm9wYWdhdGVkXG4gIC8vIHpvb20gaGVyZSBhZ2FpbnN0IHRoZSByYXcgbWluWm9vbS9tYXhab29tICh3aXRob3V0IHRoYXQgYWRqdXN0bWVudCksIFJlZHV4XG4gIC8vIGVuZHMgdXAgZGlzYWdyZWVpbmcgd2l0aCB0aGUgY29udHJvbGxlcjogdGhlIGNvbnRyb2xsZXIgbGV0cyB0aGUgdXNlciBwdWxsXG4gIC8vIHRoZSBnbG9iZSBmdXJ0aGVyIG91dCwgYnV0IHRoaXMgY2xhbXAgc25hcHMgem9vbSBiYWNrIHRvIGBtaW5ab29tYCB3aGVuIHRoZVxuICAvLyBpbnRlcmFjdGlvbidzIGluZXJ0aWEgdHJhbnNpdGlvbiBlbmRzLiBBcHBseSB0aGUgc2FtZSBhZGp1c3RtZW50IGluIGdsb2JlXG4gIC8vIG1vZGUgc28gUmVkdXggc3RheXMgY29uc2lzdGVudCB3aXRoIHRoZSBjb250cm9sbGVyIGFuZCB0aGVyZSdzIG5vIHNuYXAtYmFjay5cbiAgY29uc3QgaXNHbG9iZSA9IChuZXdWaWV3cG9ydCBhcyBhbnkpLmdsb2JlPy5lbmFibGVkO1xuXG4gIGlmIChpc0dsb2JlKSB7XG4gICAgLy8gS2VlcCB0aGUgY2FtZXJhIHRhcmdldCB3aXRoaW4gYSBsYXRpdHVkZSBiYW5kIGFyb3VuZCB0aGUgZXF1YXRvciBzbyB0aGVcbiAgICAvLyBzdG9yZWQgdmlld3BvcnQgY2FuJ3QgYmUgY2VudGVyZWQgb24gdGhlIHBvbGVzIChtYXRjaGVzIHRoZSBnbG9iZVxuICAgIC8vIGNvbnRyb2xsZXIncyBhcHBseUNvbnN0cmFpbnRzIHNvIGdlb2NvZGVyL3Byb2dyYW1tYXRpYyB1cGRhdGVzIGFncmVlKS5cbiAgICBpZiAodHlwZW9mIG5ld1ZpZXdwb3J0LmxhdGl0dWRlID09PSAnbnVtYmVyJykge1xuICAgICAgbmV3Vmlld3BvcnQubGF0aXR1ZGUgPSBNYXRoLm1pbihcbiAgICAgICAgR0xPQkVfTUFYX0xBVElUVURFLFxuICAgICAgICBNYXRoLm1heCgtR0xPQkVfTUFYX0xBVElUVURFLCBuZXdWaWV3cG9ydC5sYXRpdHVkZSlcbiAgICAgICk7XG4gICAgfVxuICAgIGNvbnN0IHpvb21BZGp1c3RtZW50ID0gTWF0aC5sb2cyKE1hdGguY29zKCgobmV3Vmlld3BvcnQubGF0aXR1ZGUgPz8gMCkgKiBNYXRoLlBJKSAvIDE4MCkpO1xuICAgIGlmIChcbiAgICAgIHR5cGVvZiBuZXdWaWV3cG9ydC5taW5ab29tID09PSAnbnVtYmVyJyAmJlxuICAgICAgdHlwZW9mIG5ld1ZpZXdwb3J0Lnpvb20gPT09ICdudW1iZXInICYmXG4gICAgICBuZXdWaWV3cG9ydC56b29tIDwgbmV3Vmlld3BvcnQubWluWm9vbSArIHpvb21BZGp1c3RtZW50XG4gICAgKSB7XG4gICAgICBuZXdWaWV3cG9ydC56b29tID0gbmV3Vmlld3BvcnQubWluWm9vbSArIHpvb21BZGp1c3RtZW50O1xuICAgIH1cbiAgICBpZiAoXG4gICAgICB0eXBlb2YgbmV3Vmlld3BvcnQubWF4Wm9vbSA9PT0gJ251bWJlcicgJiZcbiAgICAgIHR5cGVvZiBuZXdWaWV3cG9ydC56b29tID09PSAnbnVtYmVyJyAmJlxuICAgICAgbmV3Vmlld3BvcnQuem9vbSA+IG5ld1ZpZXdwb3J0Lm1heFpvb20gKyB6b29tQWRqdXN0bWVudFxuICAgICkge1xuICAgICAgbmV3Vmlld3BvcnQuem9vbSA9IG5ld1ZpZXdwb3J0Lm1heFpvb20gKyB6b29tQWRqdXN0bWVudDtcbiAgICB9XG4gIH0gZWxzZSB7XG4gICAgLy8gTWFrZSBzdXJlIHpvb20gbGV2ZWwgZG9lc24ndCBnbyBiZWxsb3cgbWluWm9vbSBpZiBkZWZpbmVkXG4gICAgaWYgKG5ld1ZpZXdwb3J0Lm1pblpvb20gJiYgbmV3Vmlld3BvcnQuem9vbSAmJiBuZXdWaWV3cG9ydC56b29tIDwgbmV3Vmlld3BvcnQubWluWm9vbSkge1xuICAgICAgbmV3Vmlld3BvcnQuem9vbSA9IG5ld1ZpZXdwb3J0Lm1pblpvb207XG4gICAgfVxuICAgIC8vIE1ha2Ugc3VyZSB6b29tIGxldmVsIGRvZXNuJ3QgZ28gYWJvdmUgbWF4Wm9vbSBpZiBkZWZpbmVkXG4gICAgaWYgKG5ld1ZpZXdwb3J0Lm1heFpvb20gJiYgbmV3Vmlld3BvcnQuem9vbSAmJiBuZXdWaWV3cG9ydC56b29tID4gbmV3Vmlld3BvcnQubWF4Wm9vbSkge1xuICAgICAgbmV3Vmlld3BvcnQuem9vbSA9IG5ld1ZpZXdwb3J0Lm1heFpvb207XG4gICAgfVxuICB9XG4gIC8vIExpbWl0IHZpZXdwb3J0IHVwZGF0ZSBiYXNlZCBvbiBtYXhCb3VuZHNcbiAgaWYgKG5ld1ZpZXdwb3J0Lm1heEJvdW5kcyAmJiB2YWxpZGF0ZUJvdW5kcyhuZXdWaWV3cG9ydC5tYXhCb3VuZHMpKSB7XG4gICAgLy8gQHRzLWV4cGVjdC1lcnJvciBUeXBlICdWaWV3cG9ydCcgaXMgbWlzc2luZyB0aGUgZm9sbG93aW5nIHByb3BlcnRpZXMgZnJvbSB0eXBlICdNYXBTdGF0ZSc6IGlzU3BsaXQsIGlzVmlld3BvcnRTeW5jZWQsIGlzWm9vbUxvY2tlZCwgc3BsaXRNYXBWaWV3cG9ydHNcbiAgICBuZXdWaWV3cG9ydCA9IHVwZGF0ZVZpZXdwb3J0QmFzZWRPbkJvdW5kcyhvcmlnaW5hbFZpZXdwb3J0LCBuZXdWaWV3cG9ydCk7XG4gIH1cblxuICByZXR1cm4gbmV3Vmlld3BvcnQ7XG59XG4iXSwibWFwcGluZ3MiOiI7Ozs7QUFBQTtBQUNBOztBQUVBLE9BQU9BLFdBQVcsTUFBTSxzQkFBc0I7QUFDOUMsU0FBUUMsYUFBYSxRQUFPLHNCQUFzQjtBQUNsRCxTQUFRQyxXQUFXLFFBQU8sb0JBQW9CO0FBQzlDLFNBQVFDLFNBQVMsUUFBTyx1QkFBdUI7QUFDL0MsT0FBT0MsU0FBUyxNQUFNLFdBQVc7QUFDakMsT0FBT0MsSUFBSSxNQUFNLGFBQWE7QUFFOUIsU0FDRUMsMEJBQTBCLEVBQzFCQyxjQUFjLEVBQ2RDLGdCQUFnQixFQUNoQkMsZ0JBQWdCLFFBQ1gsa0JBQWtCO0FBR3pCLFNBQVFDLFlBQVksRUFBRUMsV0FBVyxFQUFFQyxvQkFBb0IsRUFBRUMsY0FBYyxFQUFFQyxjQUFjLEVBQUVDLGtCQUFr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