@kepler.gl/reducers 3.3.0-alpha.5 → 3.3.0-alpha.7

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