@smarterplan/ngx-smarterplan-core 1.4.20 → 1.4.22
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.
- package/esm2022/lib/components/splat-viewer/splat-viewer.component.mjs +361 -0
- package/esm2022/lib/matterport-extensions/security-camera/SecurityCamera.mjs +28 -7
- package/esm2022/lib/ngx-smarterplan-core.module.mjs +9 -4
- package/esm2022/lib/services/matterport-object3d.service.mjs +657 -133
- package/esm2022/lib/services/matterport-tag.service.mjs +12 -7
- package/esm2022/lib/services/matterport.service.mjs +330 -9
- package/esm2022/lib/services/obj-to-glb.mjs +649 -0
- package/esm2022/lib/services/s3.service.mjs +43 -3
- package/esm2022/lib/services/threejs-import.service.mjs +6 -4
- package/esm2022/lib/services/threejs.service.mjs +867 -95
- package/esm2022/lib/services/utils/matterport-framing.util.mjs +63 -0
- package/esm2022/lib/services/viewer.service.mjs +189 -7
- package/esm2022/lib/types.service.mjs +3 -1
- package/esm2022/public-api.mjs +3 -1
- package/fesm2022/smarterplan-ngx-smarterplan-core.mjs +3217 -282
- package/fesm2022/smarterplan-ngx-smarterplan-core.mjs.map +1 -1
- package/lib/components/splat-viewer/splat-viewer.component.d.ts +98 -0
- package/lib/ngx-smarterplan-core.module.d.ts +7 -6
- package/lib/services/matterport-object3d.service.d.ts +125 -5
- package/lib/services/matterport-tag.service.d.ts +5 -5
- package/lib/services/matterport.service.d.ts +106 -7
- package/lib/services/obj-to-glb.d.ts +66 -0
- package/lib/services/s3.service.d.ts +7 -0
- package/lib/services/threejs.service.d.ts +336 -16
- package/lib/services/utils/matterport-framing.util.d.ts +40 -0
- package/lib/services/viewer.service.d.ts +110 -8
- package/lib/types.service.d.ts +42 -1
- package/package.json +1 -1
- package/public-api.d.ts +2 -0
- package/src/assets/viewers/splat/chunk-BYLI4YBI.js +17037 -0
- package/src/assets/viewers/splat/chunk-LDV6YPMG.js +1 -0
- package/src/assets/viewers/splat/chunk-WZ5Z4TU3.js +105719 -0
- package/src/assets/viewers/splat/convert-4DRLH77X.js +1 -0
- package/src/assets/viewers/splat/convert.html +11 -0
- package/src/assets/viewers/splat/converter-SLBB5MHG.js +1 -0
- package/src/assets/viewers/splat/index.html +90 -0
- package/src/assets/viewers/splat/spz-DEYRea_v-QE6YSGIB.js +5292 -0
- package/src/assets/viewers/splat/viewer-W4X3FWQJ.js +2704 -0
- package/src/assets/viewers/splat/viewer.css +1096 -0
- package/src/assets/viewers/splat/webp.wasm +0 -0
- package/src/assets/viewers/splat/worker.mjs +1383 -0
|
@@ -0,0 +1,361 @@
|
|
|
1
|
+
import { Component, EventEmitter, HostListener, Input, Output, ViewChild, } from '@angular/core';
|
|
2
|
+
import { Subject, takeUntil } from 'rxjs';
|
|
3
|
+
import { getSignedFile } from '../../services/s3.service';
|
|
4
|
+
import { VIEWER_BACKGROUND } from '../../services/threejs.service';
|
|
5
|
+
import { isStreamedSplatFile } from '../../services/viewer.service';
|
|
6
|
+
import * as i0 from "@angular/core";
|
|
7
|
+
import * as i1 from "../../services/viewer.service";
|
|
8
|
+
import * as i2 from "@angular/platform-browser";
|
|
9
|
+
import * as i3 from "@ngx-translate/core";
|
|
10
|
+
/**
|
|
11
|
+
* Gaussian splats, drawn by SuperSplat's viewer (PlayCanvas) in an iframe, as Matterport's showcase
|
|
12
|
+
* is: the page built from projects/splat-viewer, which each app serves from assets/viewers/splat.
|
|
13
|
+
*
|
|
14
|
+
* The visit's Three.js scene stays underneath, unseen, holding the tags, their calibration and the
|
|
15
|
+
* measurement, as it does for a model it draws itself; this hands the viewer what the scene holds,
|
|
16
|
+
* and turns what is clicked in it into what a click in the scene does - through ViewerService, so
|
|
17
|
+
* that whatever drives the scene (the add buttons, the calibration panel, the measuring tool, the
|
|
18
|
+
* tag lists) drives this as well. Tags clicked come out of ViewerService.threeJsTagClicked$, as
|
|
19
|
+
* clicks in the scene do.
|
|
20
|
+
*
|
|
21
|
+
* What it says of loading is for the app's own loading overlay; see the outputs.
|
|
22
|
+
*/
|
|
23
|
+
export class SplatViewerComponent {
|
|
24
|
+
viewerService;
|
|
25
|
+
host;
|
|
26
|
+
sanitizer;
|
|
27
|
+
translate;
|
|
28
|
+
/** The model: the S3 key - or assets/ path - of a splat file, or of a Streamed SOG's lod-meta.json. */
|
|
29
|
+
modelKey = null;
|
|
30
|
+
/** Which of the model's axes is up, from its capture's placement; null for the viewer's own idea. */
|
|
31
|
+
up = null;
|
|
32
|
+
/** How far loading has got, from 0 to 1, or null when the size is not known. 0 when it starts. */
|
|
33
|
+
loadProgress = new EventEmitter();
|
|
34
|
+
loaded = new EventEmitter();
|
|
35
|
+
loadFailed = new EventEmitter();
|
|
36
|
+
/** Said whenever the mode changes, the viewer's own buttons included. */
|
|
37
|
+
modeChange = new EventEmitter();
|
|
38
|
+
frame;
|
|
39
|
+
/**
|
|
40
|
+
* The viewer's page, made once, in ngOnInit: a new object, even for the same address, would make
|
|
41
|
+
* Angular set the iframe's src again, which loads the viewer afresh with nothing in it.
|
|
42
|
+
*/
|
|
43
|
+
page;
|
|
44
|
+
/** Whether the page has said it is ready; it says so again each time it starts over. */
|
|
45
|
+
ready = false;
|
|
46
|
+
/** The model handed to the page, so the same one is not downloaded twice. */
|
|
47
|
+
loadedKey = null;
|
|
48
|
+
/** Set by cancelLoad: the page, starting over empty, waits to be asked again (reload). */
|
|
49
|
+
cancelled = false;
|
|
50
|
+
/** Whether the page was last asked to take a click for a calibration. */
|
|
51
|
+
pickingForCalibration = false;
|
|
52
|
+
/** The calibration under way, as ViewerService last said. */
|
|
53
|
+
alignment = null;
|
|
54
|
+
/** Each segment's length of the measurement on the model, as ViewerService last said. */
|
|
55
|
+
measureDistances = [];
|
|
56
|
+
/** The last lod-meta.json handed to the page, as a link of this page's own. */
|
|
57
|
+
streamedMeta = null;
|
|
58
|
+
/** Pictures asked of the page, by the number they were asked with, until it answers. */
|
|
59
|
+
snapshots = new Map();
|
|
60
|
+
snapshotCount = 0;
|
|
61
|
+
destroyed$ = new Subject();
|
|
62
|
+
constructor(viewerService, host, sanitizer, translate) {
|
|
63
|
+
this.viewerService = viewerService;
|
|
64
|
+
this.host = host;
|
|
65
|
+
this.sanitizer = sanitizer;
|
|
66
|
+
this.translate = translate;
|
|
67
|
+
}
|
|
68
|
+
ngOnInit() {
|
|
69
|
+
// In the app's language, which the viewer's controls speak, and in its colours, as this element's
|
|
70
|
+
// styles take them from the app's - by now in the page, where they reach it.
|
|
71
|
+
const style = getComputedStyle(this.host.nativeElement);
|
|
72
|
+
const query = new URLSearchParams({
|
|
73
|
+
lang: this.translate.currentLang || 'en',
|
|
74
|
+
accent: style.color,
|
|
75
|
+
background: style.backgroundColor,
|
|
76
|
+
});
|
|
77
|
+
this.page = this.sanitizer.bypassSecurityTrustResourceUrl(`assets/viewers/splat/index.html?${query}`);
|
|
78
|
+
// The Three.js scene underneath has nothing to draw while this covers it, and the splat viewer
|
|
79
|
+
// needs all the graphics card there is.
|
|
80
|
+
this.viewerService.setThreeJsRenderingPaused(true);
|
|
81
|
+
const on = (source, next) => source.pipe(takeUntil(this.destroyed$)).subscribe(next);
|
|
82
|
+
on(this.viewerService.threeJsTagsChanged$, () => this.postTags());
|
|
83
|
+
// Placing a tag starts from the add buttons, the same in every viewer; the page picks the spot
|
|
84
|
+
// and says where ('picked').
|
|
85
|
+
on(this.viewerService.threeJsPlacementChanged$, (placing) => this.post({ type: 'placing', on: placing }));
|
|
86
|
+
on(this.viewerService.threeJsAlignmentProgress$, (progress) => {
|
|
87
|
+
this.alignment = progress;
|
|
88
|
+
this.postCalibration();
|
|
89
|
+
});
|
|
90
|
+
on(this.viewerService.threeJsAlignmentCancelled$, () => {
|
|
91
|
+
this.alignment = null;
|
|
92
|
+
this.postCalibration();
|
|
93
|
+
});
|
|
94
|
+
on(this.viewerService.threeJsMeasuringChanged$, (measuring) => this.post({ type: 'measuring', on: measuring }));
|
|
95
|
+
on(this.viewerService.threeJsMeasurementProgress$, (progress) => {
|
|
96
|
+
this.measureDistances = progress?.distances ?? [];
|
|
97
|
+
this.postMeasurement(!!progress);
|
|
98
|
+
});
|
|
99
|
+
// A finished measurement stays drawn while its form is open; this is when it goes.
|
|
100
|
+
on(this.viewerService.threeJsMeasurementCleared$, () => {
|
|
101
|
+
this.measureDistances = [];
|
|
102
|
+
this.postMeasurement(false);
|
|
103
|
+
});
|
|
104
|
+
// The camera sent to a tag, from a list: the page points it out.
|
|
105
|
+
on(this.viewerService.threeJsTagFocused$, (id) => this.post({ type: 'goToTag', id }));
|
|
106
|
+
}
|
|
107
|
+
ngOnChanges(changes) {
|
|
108
|
+
if (changes['modelKey'] && this.ready && !this.cancelled) {
|
|
109
|
+
void this.load();
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
ngOnDestroy() {
|
|
113
|
+
this.destroyed$.next();
|
|
114
|
+
this.destroyed$.complete();
|
|
115
|
+
this.viewerService.setThreeJsRenderingPaused(false);
|
|
116
|
+
if (this.streamedMeta) {
|
|
117
|
+
URL.revokeObjectURL(this.streamedMeta);
|
|
118
|
+
}
|
|
119
|
+
this.snapshots.forEach((resolve) => resolve(null));
|
|
120
|
+
this.snapshots.clear();
|
|
121
|
+
}
|
|
122
|
+
/** Stops the model loading; nothing is loaded again until reload(). */
|
|
123
|
+
cancelLoad() {
|
|
124
|
+
this.cancelled = true;
|
|
125
|
+
this.loadedKey = null;
|
|
126
|
+
this.post({ type: 'cancel-load' });
|
|
127
|
+
}
|
|
128
|
+
/** Loads the model again, after cancelLoad. */
|
|
129
|
+
reload() {
|
|
130
|
+
this.cancelled = false;
|
|
131
|
+
this.loadedKey = null;
|
|
132
|
+
if (this.ready) {
|
|
133
|
+
void this.load();
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
setMode(mode) {
|
|
137
|
+
this.post({ type: 'mode', mode });
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* The scene as it is on screen, with the measurement drawn on it and no tags, as a JPEG data URL;
|
|
141
|
+
* null when there is no scene to take, or the page does not answer within ten seconds.
|
|
142
|
+
*/
|
|
143
|
+
snapshot() {
|
|
144
|
+
const id = ++this.snapshotCount;
|
|
145
|
+
return new Promise((resolve) => {
|
|
146
|
+
this.snapshots.set(id, resolve);
|
|
147
|
+
this.post({ type: 'snapshot', id });
|
|
148
|
+
setTimeout(() => {
|
|
149
|
+
if (this.snapshots.delete(id)) {
|
|
150
|
+
resolve(null);
|
|
151
|
+
}
|
|
152
|
+
}, 10000);
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
/** What the page says: that it is ready, how loading goes, what was clicked in it. */
|
|
156
|
+
onMessage(event) {
|
|
157
|
+
// Only this component's page, served from this same origin.
|
|
158
|
+
if (event.source !== this.frame?.nativeElement.contentWindow || event.origin !== window.location.origin) {
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
const message = event.data;
|
|
162
|
+
const aligning = this.viewerService.isThreeJsAligningTags();
|
|
163
|
+
switch (message?.type) {
|
|
164
|
+
case 'ready':
|
|
165
|
+
// A new page, with nothing loaded or armed in it: the first, or the viewer starting over
|
|
166
|
+
// for the next model or after a cancelled load.
|
|
167
|
+
this.ready = true;
|
|
168
|
+
this.loadedKey = null;
|
|
169
|
+
this.pickingForCalibration = false;
|
|
170
|
+
if (!this.cancelled) {
|
|
171
|
+
void this.load();
|
|
172
|
+
}
|
|
173
|
+
this.postTags();
|
|
174
|
+
this.postCalibration();
|
|
175
|
+
this.post({ type: 'measuring', on: this.viewerService.isThreeJsMeasuring() });
|
|
176
|
+
this.postMeasurement(this.viewerService.getThreeJsMeasurePointsInModelFrame().length > 0);
|
|
177
|
+
break;
|
|
178
|
+
case 'progress':
|
|
179
|
+
this.loadProgress.emit(message.fraction ?? null);
|
|
180
|
+
break;
|
|
181
|
+
case 'loaded':
|
|
182
|
+
this.loaded.emit();
|
|
183
|
+
break;
|
|
184
|
+
case 'error':
|
|
185
|
+
console.error('Splat viewer:', message.message);
|
|
186
|
+
this.loadFailed.emit(String(message.message ?? ''));
|
|
187
|
+
break;
|
|
188
|
+
case 'mode':
|
|
189
|
+
this.modeChange.emit(message.mode);
|
|
190
|
+
break;
|
|
191
|
+
case 'picked':
|
|
192
|
+
if (aligning && this.alignment?.awaiting === 'point') {
|
|
193
|
+
// Where the tag being matched really is, as a click on the model in the scene would say.
|
|
194
|
+
if (!this.viewerService.matchThreeJsAlignmentTagAtModelPoint(message.position)) {
|
|
195
|
+
this.viewerService.ignoreThreeJsAlignmentClick('point');
|
|
196
|
+
}
|
|
197
|
+
break;
|
|
198
|
+
}
|
|
199
|
+
// As a click on the model in the scene: the app opens the creation form from threeJsTagPlaced$.
|
|
200
|
+
this.viewerService.placeThreeJsTagAtModelPoint(message.position, message.normal ?? null);
|
|
201
|
+
break;
|
|
202
|
+
case 'placing-cancelled':
|
|
203
|
+
// Escape, as in the scene: it ends a measurement or a calibration as it ends placing a tag.
|
|
204
|
+
if (this.viewerService.isThreeJsMeasuring()) {
|
|
205
|
+
this.viewerService.action_toolbox_cancel_mesure();
|
|
206
|
+
}
|
|
207
|
+
else if (aligning) {
|
|
208
|
+
this.viewerService.cancelThreeJsTagAlignment();
|
|
209
|
+
}
|
|
210
|
+
else {
|
|
211
|
+
this.viewerService.cancelThreeJsTagPlacement();
|
|
212
|
+
}
|
|
213
|
+
break;
|
|
214
|
+
case 'calibration-undo':
|
|
215
|
+
// Ctrl+Z or Backspace in the page, as in the scene.
|
|
216
|
+
this.viewerService.undoThreeJsAlignmentStep();
|
|
217
|
+
break;
|
|
218
|
+
case 'measure-point':
|
|
219
|
+
this.viewerService.addThreeJsMeasurePointAtModelPoint(message.position);
|
|
220
|
+
break;
|
|
221
|
+
case 'tagClick':
|
|
222
|
+
if (aligning) {
|
|
223
|
+
// Calibrating: a tag clicked is the one to match, as in the scene, and opens nothing.
|
|
224
|
+
if (this.alignment?.awaiting !== 'tag' || !this.viewerService.selectThreeJsAlignmentTag(message.id)) {
|
|
225
|
+
this.viewerService.ignoreThreeJsAlignmentClick('tag');
|
|
226
|
+
}
|
|
227
|
+
break;
|
|
228
|
+
}
|
|
229
|
+
this.viewerService.clickThreeJsTag(message.id);
|
|
230
|
+
break;
|
|
231
|
+
case 'snapshot':
|
|
232
|
+
this.snapshots.get(message.id)?.(message.image ?? null);
|
|
233
|
+
this.snapshots.delete(message.id);
|
|
234
|
+
break;
|
|
235
|
+
case 'sign': {
|
|
236
|
+
// A piece of the Streamed SOG open, by its name beside lod-meta.json.
|
|
237
|
+
const key = this.loadedKey;
|
|
238
|
+
const folder = key ? key.slice(0, key.lastIndexOf('/') + 1) : '';
|
|
239
|
+
const file = String(message.file ?? '');
|
|
240
|
+
const allowed = key && isStreamedSplatFile(key) && /^[\w.-]+$/.test(file);
|
|
241
|
+
(allowed ? getSignedFile(folder + file) : Promise.resolve(null)).then((url) => {
|
|
242
|
+
this.post({ type: 'signed', id: message.id, url });
|
|
243
|
+
});
|
|
244
|
+
break;
|
|
245
|
+
}
|
|
246
|
+
default:
|
|
247
|
+
break;
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
async load() {
|
|
251
|
+
const key = this.modelKey;
|
|
252
|
+
if (!key || key === this.loadedKey) {
|
|
253
|
+
return;
|
|
254
|
+
}
|
|
255
|
+
this.loadedKey = key;
|
|
256
|
+
this.loadProgress.emit(0);
|
|
257
|
+
let url = key.startsWith('assets/') ? key : await getSignedFile(key);
|
|
258
|
+
if (url && isStreamedSplatFile(key)) {
|
|
259
|
+
url = await this.streamedEntry(url);
|
|
260
|
+
}
|
|
261
|
+
if (this.loadedKey !== key) {
|
|
262
|
+
// Another model was asked for, or the load cancelled, while the link was being signed.
|
|
263
|
+
return;
|
|
264
|
+
}
|
|
265
|
+
this.post({ type: 'load', url, fileName: key.split('/').pop(), up: this.up });
|
|
266
|
+
}
|
|
267
|
+
/**
|
|
268
|
+
* The lod-meta.json of a Streamed SOG, with its pieces named so that the page asks for each of
|
|
269
|
+
* them when it needs it ('sign').
|
|
270
|
+
*
|
|
271
|
+
* The pieces sit beside lod-meta.json in S3 and are named relative to it, which a signed link -
|
|
272
|
+
* its signature in the query - does not survive. And they are fetched while the visit lasts, as the
|
|
273
|
+
* camera reaches them, long after any link signed up front has run out.
|
|
274
|
+
*/
|
|
275
|
+
async streamedEntry(signedMeta) {
|
|
276
|
+
const meta = await (await fetch(signedMeta)).json();
|
|
277
|
+
meta.filenames = (meta.filenames ?? []).map((name) => `https://splat.invalid/${name}`);
|
|
278
|
+
if (this.streamedMeta) {
|
|
279
|
+
URL.revokeObjectURL(this.streamedMeta);
|
|
280
|
+
}
|
|
281
|
+
this.streamedMeta = URL.createObjectURL(new Blob([JSON.stringify(meta)], { type: 'application/json' }));
|
|
282
|
+
return this.streamedMeta;
|
|
283
|
+
}
|
|
284
|
+
postTags() {
|
|
285
|
+
const { tags, alignment } = this.viewerService.getThreeJsTagSnapshot();
|
|
286
|
+
// Tags placed elsewhere - in Matterport, in another model - are in that place's coordinates,
|
|
287
|
+
// and only a calibration says where they are in this one. Without it they float off the model
|
|
288
|
+
// and seem to slide as the camera moves: they are left out until it is calibrated. A
|
|
289
|
+
// calibration under way, or its panel open, shows them all: they are what it matches.
|
|
290
|
+
const all = this.viewerService.isThreeJsCalibrated() || this.viewerService.isThreeJsShowingCalibrationTags();
|
|
291
|
+
const shown = all ? tags : tags.filter((tag) => tag.inModelFrame);
|
|
292
|
+
this.post({
|
|
293
|
+
type: 'tags',
|
|
294
|
+
tags: shown.map(({ id, position, label, iconUrl, inModelFrame, normal }) => ({ id, position, label, iconUrl, inModelFrame, normal })),
|
|
295
|
+
alignment,
|
|
296
|
+
});
|
|
297
|
+
}
|
|
298
|
+
/**
|
|
299
|
+
* The calibration under way, for the page to draw - the pins dropped, the tag being matched - and,
|
|
300
|
+
* while the place of a tag is asked for, to take the click on the model that says where ('picked').
|
|
301
|
+
*/
|
|
302
|
+
postCalibration() {
|
|
303
|
+
const on = this.viewerService.isThreeJsAligningTags() && !!this.alignment;
|
|
304
|
+
const awaiting = on ? this.alignment.awaiting : null;
|
|
305
|
+
this.post({
|
|
306
|
+
type: 'calibration',
|
|
307
|
+
calibration: on
|
|
308
|
+
? {
|
|
309
|
+
selected: awaiting === 'point' ? this.alignment.tagId ?? null : null,
|
|
310
|
+
pairs: this.alignment.matched.map(({ tagId, target }) => ({ tagId, target })),
|
|
311
|
+
}
|
|
312
|
+
: null,
|
|
313
|
+
});
|
|
314
|
+
const picking = awaiting === 'point';
|
|
315
|
+
// Only when it changes: placing a tag uses the same click, and is not to be switched off here.
|
|
316
|
+
if (picking !== this.pickingForCalibration) {
|
|
317
|
+
this.pickingForCalibration = picking;
|
|
318
|
+
this.post({ type: 'placing', on: picking });
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
/** The measurement for the page to draw - its points, each segment's length - or nothing. */
|
|
322
|
+
postMeasurement(drawn) {
|
|
323
|
+
this.post({
|
|
324
|
+
type: 'measurement',
|
|
325
|
+
measurement: drawn
|
|
326
|
+
? { points: this.viewerService.getThreeJsMeasurePointsInModelFrame(), distances: this.measureDistances }
|
|
327
|
+
: null,
|
|
328
|
+
});
|
|
329
|
+
}
|
|
330
|
+
post(command) {
|
|
331
|
+
const page = this.frame?.nativeElement.contentWindow;
|
|
332
|
+
if (page && this.ready) {
|
|
333
|
+
page.postMessage(command, window.location.origin);
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: SplatViewerComponent, deps: [{ token: i1.ViewerService }, { token: i0.ElementRef }, { token: i2.DomSanitizer }, { token: i3.TranslateService }], target: i0.ɵɵFactoryTarget.Component });
|
|
337
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: SplatViewerComponent, selector: "lib-splat-viewer", inputs: { modelKey: "modelKey", up: "up" }, outputs: { loadProgress: "loadProgress", loaded: "loaded", loadFailed: "loadFailed", modeChange: "modeChange" }, host: { listeners: { "window:message": "onMessage($event)" } }, viewQueries: [{ propertyName: "frame", first: true, predicate: ["frame"], descendants: true, static: true }], usesOnChanges: true, ngImport: i0, template: '<iframe #frame [src]="page" title="3D" allow="fullscreen; xr-spatial-tracking" allowfullscreen></iframe>', isInline: true, styles: [":host{display:block;color:var(--smarterplan-primary, rgb(83, 182, 187));background-color:var(--smarterplan-viewer-background, #e0f7ff)}iframe{display:block;width:100%;height:100%;border:0}\n"] });
|
|
338
|
+
}
|
|
339
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: SplatViewerComponent, decorators: [{
|
|
340
|
+
type: Component,
|
|
341
|
+
args: [{ selector: 'lib-splat-viewer', template: '<iframe #frame [src]="page" title="3D" allow="fullscreen; xr-spatial-tracking" allowfullscreen></iframe>', styles: [":host{display:block;color:var(--smarterplan-primary, rgb(83, 182, 187));background-color:var(--smarterplan-viewer-background, #e0f7ff)}iframe{display:block;width:100%;height:100%;border:0}\n"] }]
|
|
342
|
+
}], ctorParameters: () => [{ type: i1.ViewerService }, { type: i0.ElementRef }, { type: i2.DomSanitizer }, { type: i3.TranslateService }], propDecorators: { modelKey: [{
|
|
343
|
+
type: Input
|
|
344
|
+
}], up: [{
|
|
345
|
+
type: Input
|
|
346
|
+
}], loadProgress: [{
|
|
347
|
+
type: Output
|
|
348
|
+
}], loaded: [{
|
|
349
|
+
type: Output
|
|
350
|
+
}], loadFailed: [{
|
|
351
|
+
type: Output
|
|
352
|
+
}], modeChange: [{
|
|
353
|
+
type: Output
|
|
354
|
+
}], frame: [{
|
|
355
|
+
type: ViewChild,
|
|
356
|
+
args: ['frame', { static: true }]
|
|
357
|
+
}], onMessage: [{
|
|
358
|
+
type: HostListener,
|
|
359
|
+
args: ['window:message', ['$event']]
|
|
360
|
+
}] } });
|
|
361
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3BsYXQtdmlld2VyLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL25neC1zbWFydGVycGxhbi1jb3JlL3NyYy9saWIvY29tcG9uZW50cy9zcGxhdC12aWV3ZXIvc3BsYXQtdmlld2VyLmNvbXBvbmVudC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQ0wsU0FBUyxFQUFjLFlBQVksRUFBRSxZQUFZLEVBQUUsS0FBSyxFQUFnQyxNQUFNLEVBQWlCLFNBQVMsR0FDekgsTUFBTSxlQUFlLENBQUM7QUFHdkIsT0FBTyxFQUFFLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFFMUMsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLDJCQUEyQixDQUFDO0FBQzFELE9BQU8sRUFBNEIsaUJBQWlCLEVBQUUsTUFBTSxnQ0FBZ0MsQ0FBQztBQUM3RixPQUFPLEVBQUUsbUJBQW1CLEVBQWlCLE1BQU0sK0JBQStCLENBQUM7Ozs7O0FBS25GOzs7Ozs7Ozs7Ozs7R0FZRztBQWVILE1BQU0sT0FBTyxvQkFBb0I7SUFzRHJCO0lBQ0E7SUFDQTtJQUNBO0lBeERWLHVHQUF1RztJQUM5RixRQUFRLEdBQWtCLElBQUksQ0FBQztJQUV4QyxxR0FBcUc7SUFDNUYsRUFBRSxHQUEwQixJQUFJLENBQUM7SUFFMUMsa0dBQWtHO0lBQ3hGLFlBQVksR0FBRyxJQUFJLFlBQVksRUFBaUIsQ0FBQztJQUVqRCxNQUFNLEdBQUcsSUFBSSxZQUFZLEVBQVEsQ0FBQztJQUVsQyxVQUFVLEdBQUcsSUFBSSxZQUFZLEVBQVUsQ0FBQztJQUVsRCx5RUFBeUU7SUFDL0QsVUFBVSxHQUFHLElBQUksWUFBWSxFQUFtQixDQUFDO0lBRXJCLEtBQUssQ0FBaUM7SUFFNUU7OztPQUdHO0lBQ0gsSUFBSSxDQUFtQjtJQUV2Qix3RkFBd0Y7SUFDaEYsS0FBSyxHQUFHLEtBQUssQ0FBQztJQUV0Qiw2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RixlQUFlLENBQUMsS0FBYztRQUNwQyxJQUFJLENBQUMsSUFBSSxDQUFDO1lBQ1IsSUFBSSxFQUFFLGFBQWE7WUFDbkIsV0FBVyxFQUFFLEtBQUs7Z0JBQ2hCLENBQUMsQ0FBQyxFQUFFLE1BQU0sRUFBRSxJQUFJLENBQUMsYUFBYSxDQUFDLG1DQUFtQyxFQUFFLEVBQUUsU0FBUyxFQUFFLElBQUksQ0FBQyxnQkFBZ0IsRUFBRTtnQkFDeEcsQ0FBQyxDQUFDLElBQUk7U0FDVCxDQUFDLENBQUM7SUFDTCxDQUFDO0lBRU8sSUFBSSxDQUFDLE9BQWU7UUFDMUIsTUFBTSxJQUFJLEdBQUcsSUFBSSxDQUFDLEtBQUssRUFBRSxhQUFhLENBQUMsYUFBYSxDQUFDO1FBQ3JELElBQUksSUFBSSxJQUFJLElBQUksQ0FBQyxLQUFLLEVBQUUsQ0FBQztZQUN2QixJQUFJLENBQUMsV0FBVyxDQUFDLE9BQU8sRUFBRSxNQUFNLENBQUMsUUFBUSxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBQ3BELENBQUM7SUFDSCxDQUFDO3dHQXRWVSxvQkFBb0I7NEZBQXBCLG9CQUFvQix3WkFackIsMEdBQTBHOzs0RkFZekcsb0JBQW9CO2tCQWRoQyxTQUFTOytCQUNFLGtCQUFrQixZQUNsQiwwR0FBMEc7cUtBYzNHLFFBQVE7c0JBQWhCLEtBQUs7Z0JBR0csRUFBRTtzQkFBVixLQUFLO2dCQUdJLFlBQVk7c0JBQXJCLE1BQU07Z0JBRUcsTUFBTTtzQkFBZixNQUFNO2dCQUVHLFVBQVU7c0JBQW5CLE1BQU07Z0JBR0csVUFBVTtzQkFBbkIsTUFBTTtnQkFFK0IsS0FBSztzQkFBMUMsU0FBUzt1QkFBQyxPQUFPLEVBQUUsRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFO2dCQThJcEMsU0FBUztzQkFEUixZQUFZO3VCQUFDLGdCQUFnQixFQUFFLENBQUMsUUFBUSxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcbiAgQ29tcG9uZW50LCBFbGVtZW50UmVmLCBFdmVudEVtaXR0ZXIsIEhvc3RMaXN0ZW5lciwgSW5wdXQsIE9uQ2hhbmdlcywgT25EZXN0cm95LCBPbkluaXQsIE91dHB1dCwgU2ltcGxlQ2hhbmdlcywgVmlld0NoaWxkLFxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IERvbVNhbml0aXplciwgU2FmZVJlc291cmNlVXJsIH0gZnJvbSAnQGFuZ3VsYXIvcGxhdGZvcm0tYnJvd3Nlcic7XG5pbXBvcnQgeyBUcmFuc2xhdGVTZXJ2aWNlIH0gZnJvbSAnQG5neC10cmFuc2xhdGUvY29yZSc7XG5pbXBvcnQgeyBTdWJqZWN0LCB0YWtlVW50aWwgfSBmcm9tICdyeGpzJztcbmltcG9ydCB7IFRocmVlSnNNb2RlbFVwIH0gZnJvbSAnLi4vLi4vaGVscGVycy5zZXJ2aWNlJztcbmltcG9ydCB7IGdldFNpZ25lZEZpbGUgfSBmcm9tICcuLi8uLi9zZXJ2aWNlcy9zMy5zZXJ2aWNlJztcbmltcG9ydCB7IFRocmVlSnNBbGlnbm1lbnRQcm9ncmVzcywgVklFV0VSX0JBQ0tHUk9VTkQgfSBmcm9tICcuLi8uLi9zZXJ2aWNlcy90aHJlZWpzLnNlcnZpY2UnO1xuaW1wb3J0IHsgaXNTdHJlYW1lZFNwbGF0RmlsZSwgVmlld2VyU2VydmljZSB9IGZyb20gJy4uLy4uL3NlcnZpY2VzL3ZpZXdlci5zZXJ2aWNlJztcblxuLyoqIEhvdyB0aGUgc3BsYXQgdmlld2VyIGlzIG1vdmVkIHRocm91Z2g6IGFyb3VuZCB0aGUgbW9kZWwsIG9yIGluc2lkZSBpdC4gKi9cbmV4cG9ydCB0eXBlIFNwbGF0Vmlld2VyTW9kZSA9ICdvcmJpdCcgfCAnd2Fsayc7XG5cbi8qKlxuICogR2F1c3NpYW4gc3BsYXRzLCBkcmF3biBieSBTdXBlclNwbGF0J3Mgdmlld2VyIChQbGF5Q2FudmFzKSBpbiBhbiBpZnJhbWUsIGFzIE1hdHRlcnBvcnQncyBzaG93Y2FzZVxuICogaXM6IHRoZSBwYWdlIGJ1aWx0IGZyb20gcHJvamVjdHMvc3BsYXQtdmlld2VyLCB3aGljaCBlYWNoIGFwcCBzZXJ2ZXMgZnJvbSBhc3NldHMvdmlld2Vycy9zcGxhdC5cbiAqXG4gKiBUaGUgdmlzaXQncyBUaHJlZS5qcyBzY2VuZSBzdGF5cyB1bmRlcm5lYXRoLCB1bnNlZW4sIGhvbGRpbmcgdGhlIHRhZ3MsIHRoZWlyIGNhbGlicmF0aW9uIGFuZCB0aGVcbiAqIG1lYXN1cmVtZW50LCBhcyBpdCBkb2VzIGZvciBhIG1vZGVsIGl0IGRyYXdzIGl0c2VsZjsgdGhpcyBoYW5kcyB0aGUgdmlld2VyIHdoYXQgdGhlIHNjZW5lIGhvbGRzLFxuICogYW5kIHR1cm5zIHdoYXQgaXMgY2xpY2tlZCBpbiBpdCBpbnRvIHdoYXQgYSBjbGljayBpbiB0aGUgc2NlbmUgZG9lcyAtIHRocm91Z2ggVmlld2VyU2VydmljZSwgc29cbiAqIHRoYXQgd2hhdGV2ZXIgZHJpdmVzIHRoZSBzY2VuZSAodGhlIGFkZCBidXR0b25zLCB0aGUgY2FsaWJyYXRpb24gcGFuZWwsIHRoZSBtZWFzdXJpbmcgdG9vbCwgdGhlXG4gKiB0YWcgbGlzdHMpIGRyaXZlcyB0aGlzIGFzIHdlbGwuIFRhZ3MgY2xpY2tlZCBjb21lIG91dCBvZiBWaWV3ZXJTZXJ2aWNlLnRocmVlSnNUYWdDbGlja2VkJCwgYXNcbiAqIGNsaWNrcyBpbiB0aGUgc2NlbmUgZG8uXG4gKlxuICogV2hhdCBpdCBzYXlzIG9mIGxvYWRpbmcgaXMgZm9yIHRoZSBhcHAncyBvd24gbG9hZGluZyBvdmVybGF5OyBzZWUgdGhlIG91dHB1dHMuXG4gKi9cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ2xpYi1zcGxhdC12aWV3ZXInLFxuICB0ZW1wbGF0ZTogJzxpZnJhbWUgI2ZyYW1lIFtzcmNdPVwicGFnZVwiIHRpdGxlPVwiM0RcIiBhbGxvdz1cImZ1bGxzY3JlZW47IHhyLXNwYXRpYWwtdHJhY2tpbmdcIiBhbGxvd2Z1bGxzY3JlZW4+PC9pZnJhbWU+JyxcbiAgLy8gVGhlIGFwcCdzIGNvbG91cnMsIHdoaWNoIHRoZSBwYWdlIGlzIG9wZW5lZCB3aXRoIChzZWUgbmdPbkluaXQpOiBjb2xvciBpcyBpdHMgcHJpbWFyeSwgZm9yIHRoZVxuICAvLyB2aWV3ZXIncyBjb250cm9scywgYW5kIGJhY2tncm91bmQtY29sb3IgdGhlIDNEIHZpZXdlcnMnIGJhY2tncm91bmQsIHRoZSBUaHJlZS5qcyBzY2VuZSdzIHRvby5cbiAgc3R5bGVzOiBbYFxuICAgIDpob3N0IHtcbiAgICAgIGRpc3BsYXk6IGJsb2NrO1xuICAgICAgY29sb3I6IHZhcigtLXNtYXJ0ZXJwbGFuLXByaW1hcnksIHJnYig4MywgMTgyLCAxODcpKTtcbiAgICAgIGJhY2tncm91bmQtY29sb3I6IHZhcigtLXNtYXJ0ZXJwbGFuLXZpZXdlci1iYWNrZ3JvdW5kLCAke1ZJRVdFUl9CQUNLR1JPVU5EfSk7XG4gICAgfVxuICAgIGlmcmFtZSB7IGRpc3BsYXk6IGJsb2NrOyB3aWR0aDogMTAwJTsgaGVpZ2h0OiAxMDAlOyBib3JkZXI6IDA7IH1cbiAgYF0sXG59KVxuZXhwb3J0IGNsYXNzIFNwbGF0Vmlld2VyQ29tcG9uZW50IGltcGxlbWVudHMgT25Jbml0LCBPbkNoYW5nZXMsIE9uRGVzdHJveSB7XG4gIC8qKiBUaGUgbW9kZWw6IHRoZSBTMyBrZXkgLSBvciBhc3NldHMvIHBhdGggLSBvZiBhIHNwbGF0IGZpbGUsIG9yIG9mIGEgU3RyZWFtZWQgU09HJ3MgbG9kLW1ldGEuanNvbi4gKi9cbiAgQElucHV0KCkgbW9kZWxLZXk6IHN0cmluZyB8IG51bGwgPSBudWxsO1xuXG4gIC8qKiBXaGljaCBvZiB0aGUgbW9kZWwncyBheGVzIGlzIHVwLCBmcm9tIGl0cyBjYXB0dXJlJ3MgcGxhY2VtZW50OyBudWxsIGZvciB0aGUgdmlld2VyJ3Mgb3duIGlkZWEuICovXG4gIEBJbnB1dCgpIHVwOiBUaHJlZUpzTW9kZWxVcCB8IG51bGwgPSBudWxsO1xuXG4gIC8qKiBIb3cgZmFyIGxvYWRpbmcgaGFzIGdvdCwgZnJvbSAwIHRvIDEsIG9yIG51bGwgd2hlbiB0aGUgc2l6ZSBpcyBub3Qga25vd24uIDAgd2hlbiBpdCBzdGFydHMuICovXG4gIEBPdXRwdXQoKSBsb2FkUHJvZ3Jlc3MgPSBuZXcgRXZlbnRFbWl0dGVyPG51bWJlciB8IG51bGw+KCk7XG5cbiAgQE91dHB1dCgpIGxvYWRlZCA9IG5ldyBFdmVudEVtaXR0ZXI8dm9pZD4oKTtcblxuICBAT3V0cHV0KCkgbG9hZEZhaWxlZCA9IG5ldyBFdmVudEVtaXR0ZXI8c3RyaW5nPigpO1xuXG4gIC8qKiBTYWlkIHdoZW5ldmVyIHRoZSBtb2RlIGNoYW5nZXMsIHRoZSB2aWV3ZXIncyBvd24gYnV0dG9ucyBpbmNsdWRlZC4gKi9cbiAgQE91dHB1dCgpIG1vZGVDaGFuZ2UgPSBuZXcgRXZlbnRFbWl0dGVyPFNwbGF0Vmlld2VyTW9kZT4oKTtcblxuICBAVmlld0NoaWxkKCdmcmFtZScsIHsgc3RhdGljOiB0cnVlIH0pIGZyYW1lITogRWxlbWVudFJlZjxIVE1MSUZyYW1lRWxlbWVudD47XG5cbiAgLyoqXG4gICAqIFRoZSB2aWV3ZXIncyBwYWdlLCBtYWRlIG9uY2UsIGluIG5nT25Jbml0OiBhIG5ldyBvYmplY3QsIGV2ZW4gZm9yIHRoZSBzYW1lIGFkZHJlc3MsIHdvdWxkIG1ha2VcbiAgICogQW5ndWxhciBzZXQgdGhlIGlmcmFtZSdzIHNyYyBhZ2Fpbiwgd2hpY2ggbG9hZHMgdGhlIHZpZXdlciBhZnJlc2ggd2l0aCBub3RoaW5nIGluIGl0LlxuICAgKi9cbiAgcGFnZSE6IFNhZmVSZXNvdXJjZVVybDtcblxuICAvKiogV2hldGhlciB0aGUgcGFnZSBoYXMgc2FpZCBpdCBpcyByZWFkeTsgaXQgc2F5cyBzbyBhZ2FpbiBlYWNoIHRpbWUgaXQgc3RhcnRzIG92ZXIuICovXG4gIHByaXZhdGUgcmVhZHkgPSBmYWxzZTtcblxuICAvKiogVGhlIG1vZGVsIGhhbmRlZCB0byB0aGUgcGFnZSwgc28gdGhlIHNhbWUgb25lIGlzIG5vdCBkb3dubG9hZGVkIHR3aWNlLiAqL1xuICBwcml2YXRlIGxvYWRlZEtleTogc3RyaW5nIHwgbnVsbCA9IG51bGw7XG5cbiAgLyoqIFNldCBieSBjYW5jZWxMb2FkOiB0aGUgcGFnZSwgc3RhcnRpbmcgb3ZlciBlbXB0eSwgd2FpdHMgdG8gYmUgYXNrZWQgYWdhaW4gKHJlbG9hZCkuICovXG4gIHByaXZhdGUgY2FuY2VsbGVkID0gZmFsc2U7XG5cbiAgLyoqIFdoZXRoZXIgdGhlIHBhZ2Ugd2FzIGxhc3QgYXNrZWQgdG8gdGFrZSBhIGNsaWNrIGZvciBhIGNhbGlicmF0aW9uLiAqL1xuICBwcml2YXRlIHBpY2tpbmdGb3JDYWxpYnJhdGlvbiA9IGZhbHNlO1xuXG4gIC8qKiBUaGUgY2FsaWJyYXRpb24gdW5kZXIgd2F5LCBhcyBWaWV3ZXJTZXJ2aWNlIGxhc3Qgc2FpZC4gKi9cbiAgcHJpdmF0ZSBhbGlnbm1lbnQ6IFRocmVlSnNBbGlnbm1lbnRQcm9ncmVzcyB8IG51bGwgPSBudWxsO1xuXG4gIC8qKiBFYWNoIHNlZ21lbnQncyBsZW5ndGggb2YgdGhlIG1lYXN1cmVtZW50IG9uIHRoZSBtb2RlbCwgYXMgVmlld2VyU2VydmljZSBsYXN0IHNhaWQuICovXG4gIHByaXZhdGUgbWVhc3VyZURpc3RhbmNlczogbnVtYmVyW10gPSBbXTtcblxuICAvKiogVGhlIGxhc3QgbG9kLW1ldGEuanNvbiBoYW5kZWQgdG8gdGhlIHBhZ2UsIGFzIGEgbGluayBvZiB0aGlzIHBhZ2UncyBvd24uICovXG4gIHByaXZhdGUgc3RyZWFtZWRNZXRhOiBzdHJpbmcgfCBudWxsID0gbnVsbDtcblxuICAvKiogUGljdHVyZXMgYXNrZWQgb2YgdGhlIHBhZ2UsIGJ5IHRoZSBudW1iZXIgdGhleSB3ZXJlIGFza2VkIHdpdGgsIHVudGlsIGl0IGFuc3dlcnMuICovXG4gIHByaXZhdGUgc25hcHNob3RzID0gbmV3IE1hcDxudW1iZXIsIChpbWFnZTogc3RyaW5nIHwgbnVsbCkgPT4gdm9pZD4oKTtcblxuICBwcml2YXRlIHNuYXBzaG90Q291bnQgPSAwO1xuXG4gIHByaXZhdGUgZGVzdHJveWVkJCA9IG5ldyBTdWJqZWN0PHZvaWQ+KCk7XG5cbiAgY29uc3RydWN0b3IoXG4gICAgcHJpdmF0ZSB2aWV3ZXJTZXJ2aWNlOiBWaWV3ZXJTZXJ2aWNlLFxuICAgIHByaXZhdGUgaG9zdDogRWxlbWVudFJlZjxIVE1MRWxlbWVudD4sXG4gICAgcHJpdmF0ZSBzYW5pdGl6ZXI6IERvbVNhbml0aXplcixcbiAgICBwcml2YXRlIHRyYW5zbGF0ZTogVHJhbnNsYXRlU2VydmljZSxcbiAgKSB7fVxuXG4gIG5nT25Jbml0KCk6IHZvaWQge1xuICAgIC8vIEluIHRoZSBhcHAncyBsYW5ndWFnZSwgd2hpY2ggdGhlIHZpZXdlcidzIGNvbnRyb2xzIHNwZWFrLCBhbmQgaW4gaXRzIGNvbG91cnMsIGFzIHRoaXMgZWxlbWVudCdzXG4gICAgLy8gc3R5bGVzIHRha2UgdGhlbSBmcm9tIHRoZSBhcHAncyAtIGJ5IG5vdyBpbiB0aGUgcGFnZSwgd2hlcmUgdGhleSByZWFjaCBpdC5cbiAgICBjb25zdCBzdHlsZSA9IGdldENvbXB1dGVkU3R5bGUodGhpcy5ob3N0Lm5hdGl2ZUVsZW1lbnQpO1xuICAgIGNvbnN0IHF1ZXJ5ID0gbmV3IFVSTFNlYXJjaFBhcmFtcyh7XG4gICAgICBsYW5nOiB0aGlzLnRyYW5zbGF0ZS5jdXJyZW50TGFuZyB8fCAnZW4nLFxuICAgICAgYWNjZW50OiBzdHlsZS5jb2xvcixcbiAgICAgIGJhY2tncm91bmQ6IHN0eWxlLmJhY2tncm91bmRDb2xvcixcbiAgICB9KTtcbiAgICB0aGlzLnBhZ2UgPSB0aGlzLnNhbml0aXplci5ieXBhc3NTZWN1cml0eVRydXN0UmVzb3VyY2VVcmwoYGFzc2V0cy92aWV3ZXJzL3NwbGF0L2luZGV4Lmh0bWw/JHtxdWVyeX1gKTtcblxuICAgIC8vIFRoZSBUaHJlZS5qcyBzY2VuZSB1bmRlcm5lYXRoIGhhcyBub3RoaW5nIHRvIGRyYXcgd2hpbGUgdGhpcyBjb3ZlcnMgaXQsIGFuZCB0aGUgc3BsYXQgdmlld2VyXG4gICAgLy8gbmVlZHMgYWxsIHRoZSBncmFwaGljcyBjYXJkIHRoZXJlIGlzLlxuICAgIHRoaXMudmlld2VyU2VydmljZS5zZXRUaHJlZUpzUmVuZGVyaW5nUGF1c2VkKHRydWUpO1xuICAgIGNvbnN0IG9uID0gPFQ+KHNvdXJjZTogeyBwaXBlOiBGdW5jdGlvbiB9LCBuZXh0OiAodmFsdWU6IFQpID0+IHZvaWQpID0+XG4gICAgICAoc291cmNlLnBpcGUodGFrZVVudGlsKHRoaXMuZGVzdHJveWVkJCkpIGFzIGFueSkuc3Vic2NyaWJlKG5leHQpO1xuXG4gICAgb24odGhpcy52aWV3ZXJTZXJ2aWNlLnRocmVlSnNUYWdzQ2hhbmdlZCQsICgpID0+IHRoaXMucG9zdFRhZ3MoKSk7XG4gICAgLy8gUGxhY2luZyBhIHRhZyBzdGFydHMgZnJvbSB0aGUgYWRkIGJ1dHRvbnMsIHRoZSBzYW1lIGluIGV2ZXJ5IHZpZXdlcjsgdGhlIHBhZ2UgcGlja3MgdGhlIHNwb3RcbiAgICAvLyBhbmQgc2F5cyB3aGVyZSAoJ3BpY2tlZCcpLlxuICAgIG9uPGJvb2xlYW4+KHRoaXMudmlld2VyU2VydmljZS50aHJlZUpzUGxhY2VtZW50Q2hhbmdlZCQsIChwbGFjaW5nKSA9PiB0aGlzLnBvc3QoeyB0eXBlOiAncGxhY2luZycsIG9uOiBwbGFjaW5nIH0pKTtcbiAgICBvbjxUaHJlZUpzQWxpZ25tZW50UHJvZ3Jlc3M+KHRoaXMudmlld2VyU2VydmljZS50aHJlZUpzQWxpZ25tZW50UHJvZ3Jlc3MkLCAocHJvZ3Jlc3MpID0+IHtcbiAgICAgIHRoaXMuYWxpZ25tZW50ID0gcHJvZ3Jlc3M7XG4gICAgICB0aGlzLnBvc3RDYWxpYnJhdGlvbigpO1xuICAgIH0pO1xuICAgIG9uKHRoaXMudmlld2VyU2VydmljZS50aHJlZUpzQWxpZ25tZW50Q2FuY2VsbGVkJCwgKCkgPT4ge1xuICAgICAgdGhpcy5hbGlnbm1lbnQgPSBudWxsO1xuICAgICAgdGhpcy5wb3N0Q2FsaWJyYXRpb24oKTtcbiAgICB9KTtcbiAgICBvbjxib29sZWFuPih0aGlzLnZpZXdlclNlcnZpY2UudGhyZWVKc01lYXN1cmluZ0NoYW5nZWQkLCAobWVhc3VyaW5nKSA9PiB0aGlzLnBvc3QoeyB0eXBlOiAnbWVhc3VyaW5nJywgb246IG1lYXN1cmluZyB9KSk7XG4gICAgb248eyBwb2ludHM6IG51bWJlcjsgZGlzdGFuY2VzOiBudW1iZXJbXSB9IHwgbnVsbD4odGhpcy52aWV3ZXJTZXJ2aWNlLnRocmVlSnNNZWFzdXJlbWVudFByb2dyZXNzJCwgKHByb2dyZXNzKSA9PiB7XG4gICAgICB0aGlzLm1lYXN1cmVEaXN0YW5jZXMgPSBwcm9ncmVzcz8uZGlzdGFuY2VzID8/IFtdO1xuICAgICAgdGhpcy5wb3N0TWVhc3VyZW1lbnQoISFwcm9ncmVzcyk7XG4gICAgfSk7XG4gICAgLy8gQSBmaW5pc2hlZCBtZWFzdXJlbWVudCBzdGF5cyBkcmF3biB3aGlsZSBpdHMgZm9ybSBpcyBvcGVuOyB0aGlzIGlzIHdoZW4gaXQgZ29lcy5cbiAgICBvbih0aGlzLnZpZXdlclNlcnZpY2UudGhyZWVKc01lYXN1cmVtZW50Q2xlYXJlZCQsICgpID0+IHtcbiAgICAgIHRoaXMubWVhc3VyZURpc3RhbmNlcyA9IFtdO1xuICAgICAgdGhpcy5wb3N0TWVhc3VyZW1lbnQoZmFsc2UpO1xuICAgIH0pO1xuICAgIC8vIFRoZSBjYW1lcmEgc2VudCB0byBhIHRhZywgZnJvbSBhIGxpc3Q6IHRoZSBwYWdlIHBvaW50cyBpdCBvdXQuXG4gICAgb248c3RyaW5nPih0aGlzLnZpZXdlclNlcnZpY2UudGhyZWVKc1RhZ0ZvY3VzZWQkLCAoaWQpID0+IHRoaXMucG9zdCh7IHR5cGU6ICdnb1RvVGFnJywgaWQgfSkpO1xuICB9XG5cbiAgbmdPbkNoYW5nZXMoY2hhbmdlczogU2ltcGxlQ2hhbmdlcyk6IHZvaWQge1xuICAgIGlmIChjaGFuZ2VzWydtb2RlbEtleSddICYmIHRoaXMucmVhZHkgJiYgIXRoaXMuY2FuY2VsbGVkKSB7XG4gICAgICB2b2lkIHRoaXMubG9hZCgpO1xuICAgIH1cbiAgfVxuXG4gIG5nT25EZXN0cm95KCk6IHZvaWQge1xuICAgIHRoaXMuZGVzdHJveWVkJC5uZXh0KCk7XG4gICAgdGhpcy5kZXN0cm95ZWQkLmNvbXBsZXRlKCk7XG4gICAgdGhpcy52aWV3ZXJTZXJ2aWNlLnNldFRocmVlSnNSZW5kZXJpbmdQYXVzZWQoZmFsc2UpO1xuICAgIGlmICh0aGlzLnN0cmVhbWVkTWV0YSkge1xuICAgICAgVVJMLnJldm9rZU9iamVjdFVSTCh0aGlzLnN0cmVhbWVkTWV0YSk7XG4gICAgfVxuICAgIHRoaXMuc25hcHNob3RzLmZvckVhY2goKHJlc29sdmUpID0+IHJlc29sdmUobnVsbCkpO1xuICAgIHRoaXMuc25hcHNob3RzLmNsZWFyKCk7XG4gIH1cblxuICAvKiogU3RvcHMgdGhlIG1vZGVsIGxvYWRpbmc7IG5vdGhpbmcgaXMgbG9hZGVkIGFnYWluIHVudGlsIHJlbG9hZCgpLiAqL1xuICBjYW5jZWxMb2FkKCk6IHZvaWQge1xuICAgIHRoaXMuY2FuY2VsbGVkID0gdHJ1ZTtcbiAgICB0aGlzLmxvYWRlZEtleSA9IG51bGw7XG4gICAgdGhpcy5wb3N0KHsgdHlwZTogJ2NhbmNlbC1sb2FkJyB9KTtcbiAgfVxuXG4gIC8qKiBMb2FkcyB0aGUgbW9kZWwgYWdhaW4sIGFmdGVyIGNhbmNlbExvYWQuICovXG4gIHJlbG9hZCgpOiB2b2lkIHtcbiAgICB0aGlzLmNhbmNlbGxlZCA9IGZhbHNlO1xuICAgIHRoaXMubG9hZGVkS2V5ID0gbnVsbDtcbiAgICBpZiAodGhpcy5yZWFkeSkge1xuICAgICAgdm9pZCB0aGlzLmxvYWQoKTtcbiAgICB9XG4gIH1cblxuICBzZXRNb2RlKG1vZGU6IFNwbGF0Vmlld2VyTW9kZSk6IHZvaWQge1xuICAgIHRoaXMucG9zdCh7IHR5cGU6ICdtb2RlJywgbW9kZSB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBUaGUgc2NlbmUgYXMgaXQgaXMgb24gc2NyZWVuLCB3aXRoIHRoZSBtZWFzdXJlbWVudCBkcmF3biBvbiBpdCBhbmQgbm8gdGFncywgYXMgYSBKUEVHIGRhdGEgVVJMO1xuICAgKiBudWxsIHdoZW4gdGhlcmUgaXMgbm8gc2NlbmUgdG8gdGFrZSwgb3IgdGhlIHBhZ2UgZG9lcyBub3QgYW5zd2VyIHdpdGhpbiB0ZW4gc2Vjb25kcy5cbiAgICovXG4gIHNuYXBzaG90KCk6IFByb21pc2U8c3RyaW5nIHwgbnVsbD4ge1xuICAgIGNvbnN0IGlkID0gKyt0aGlzLnNuYXBzaG90Q291bnQ7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlKSA9PiB7XG4gICAgICB0aGlzLnNuYXBzaG90cy5zZXQoaWQsIHJlc29sdmUpO1xuICAgICAgdGhpcy5wb3N0KHsgdHlwZTogJ3NuYXBzaG90JywgaWQgfSk7XG4gICAgICBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgICAgaWYgKHRoaXMuc25hcHNob3RzLmRlbGV0ZShpZCkpIHtcbiAgICAgICAgICByZXNvbHZlKG51bGwpO1xuICAgICAgICB9XG4gICAgICB9LCAxMDAwMCk7XG4gICAgfSk7XG4gIH1cblxuICAvKiogV2hhdCB0aGUgcGFnZSBzYXlzOiB0aGF0IGl0IGlzIHJlYWR5LCBob3cgbG9hZGluZyBnb2VzLCB3aGF0IHdhcyBjbGlja2VkIGluIGl0LiAqL1xuICBASG9zdExpc3RlbmVyKCd3aW5kb3c6bWVzc2FnZScsIFsnJGV2ZW50J10pXG4gIG9uTWVzc2FnZShldmVudDogTWVzc2FnZUV2ZW50KTogdm9pZCB7XG4gICAgLy8gT25seSB0aGlzIGNvbXBvbmVudCdzIHBhZ2UsIHNlcnZlZCBmcm9tIHRoaXMgc2FtZSBvcmlnaW4uXG4gICAgaWYgKGV2ZW50LnNvdXJjZSAhPT0gdGhpcy5mcmFtZT8ubmF0aXZlRWxlbWVudC5jb250ZW50V2luZG93IHx8IGV2ZW50Lm9yaWdpbiAhPT0gd2luZG93LmxvY2F0aW9uLm9yaWdpbikge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBjb25zdCBtZXNzYWdlID0gZXZlbnQuZGF0YTtcbiAgICBjb25zdCBhbGlnbmluZyA9IHRoaXMudmlld2VyU2VydmljZS5pc1RocmVlSnNBbGlnbmluZ1RhZ3MoKTtcbiAgICBzd2l0Y2ggKG1lc3NhZ2U/LnR5cGUpIHtcbiAgICAgIGNhc2UgJ3JlYWR5JzpcbiAgICAgICAgLy8gQSBuZXcgcGFnZSwgd2l0aCBub3RoaW5nIGxvYWRlZCBvciBhcm1lZCBpbiBpdDogdGhlIGZpcnN0LCBvciB0aGUgdmlld2VyIHN0YXJ0aW5nIG92ZXJcbiAgICAgICAgLy8gZm9yIHRoZSBuZXh0IG1vZGVsIG9yIGFmdGVyIGEgY2FuY2VsbGVkIGxvYWQuXG4gICAgICAgIHRoaXMucmVhZHkgPSB0cnVlO1xuICAgICAgICB0aGlzLmxvYWRlZEtleSA9IG51bGw7XG4gICAgICAgIHRoaXMucGlja2luZ0ZvckNhbGlicmF0aW9uID0gZmFsc2U7XG4gICAgICAgIGlmICghdGhpcy5jYW5jZWxsZWQpIHtcbiAgICAgICAgICB2b2lkIHRoaXMubG9hZCgpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMucG9zdFRhZ3MoKTtcbiAgICAgICAgdGhpcy5wb3N0Q2FsaWJyYXRpb24oKTtcbiAgICAgICAgdGhpcy5wb3N0KHsgdHlwZTogJ21lYXN1cmluZycsIG9uOiB0aGlzLnZpZXdlclNlcnZpY2UuaXNUaHJlZUpzTWVhc3VyaW5nKCkgfSk7XG4gICAgICAgIHRoaXMucG9zdE1lYXN1cmVtZW50KHRoaXMudmlld2VyU2VydmljZS5nZXRUaHJlZUpzTWVhc3VyZVBvaW50c0luTW9kZWxGcmFtZSgpLmxlbmd0aCA+IDApO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJ3Byb2dyZXNzJzpcbiAgICAgICAgdGhpcy5sb2FkUHJvZ3Jlc3MuZW1pdChtZXNzYWdlLmZyYWN0aW9uID8/IG51bGwpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJ2xvYWRlZCc6XG4gICAgICAgIHRoaXMubG9hZGVkLmVtaXQoKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICdlcnJvcic6XG4gICAgICAgIGNvbnNvbGUuZXJyb3IoJ1NwbGF0IHZpZXdlcjonLCBtZXNzYWdlLm1lc3NhZ2UpO1xuICAgICAgICB0aGlzLmxvYWRGYWlsZWQuZW1pdChTdHJpbmcobWVzc2FnZS5tZXNzYWdlID8/ICcnKSk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAnbW9kZSc6XG4gICAgICAgIHRoaXMubW9kZUNoYW5nZS5lbWl0KG1lc3NhZ2UubW9kZSk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAncGlja2VkJzpcbiAgICAgICAgaWYgKGFsaWduaW5nICYmIHRoaXMuYWxpZ25tZW50Py5hd2FpdGluZyA9PT0gJ3BvaW50Jykge1xuICAgICAgICAgIC8vIFdoZXJlIHRoZSB0YWcgYmVpbmcgbWF0Y2hlZCByZWFsbHkgaXMsIGFzIGEgY2xpY2sgb24gdGhlIG1vZGVsIGluIHRoZSBzY2VuZSB3b3VsZCBzYXkuXG4gICAgICAgICAgaWYgKCF0aGlzLnZpZXdlclNlcnZpY2UubWF0Y2hUaHJlZUpzQWxpZ25tZW50VGFnQXRNb2RlbFBvaW50KG1lc3NhZ2UucG9zaXRpb24pKSB7XG4gICAgICAgICAgICB0aGlzLnZpZXdlclNlcnZpY2UuaWdub3JlVGhyZWVKc0FsaWdubWVudENsaWNrKCdwb2ludCcpO1xuICAgICAgICAgIH1cbiAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgICAgICAvLyBBcyBhIGNsaWNrIG9uIHRoZSBtb2RlbCBpbiB0aGUgc2NlbmU6IHRoZSBhcHAgb3BlbnMgdGhlIGNyZWF0aW9uIGZvcm0gZnJvbSB0aHJlZUpzVGFnUGxhY2VkJC5cbiAgICAgICAgdGhpcy52aWV3ZXJTZXJ2aWNlLnBsYWNlVGhyZWVKc1RhZ0F0TW9kZWxQb2ludChtZXNzYWdlLnBvc2l0aW9uLCBtZXNzYWdlLm5vcm1hbCA/PyBudWxsKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICdwbGFjaW5nLWNhbmNlbGxlZCc6XG4gICAgICAgIC8vIEVzY2FwZSwgYXMgaW4gdGhlIHNjZW5lOiBpdCBlbmRzIGEgbWVhc3VyZW1lbnQgb3IgYSBjYWxpYnJhdGlvbiBhcyBpdCBlbmRzIHBsYWNpbmcgYSB0YWcuXG4gICAgICAgIGlmICh0aGlzLnZpZXdlclNlcnZpY2UuaXNUaHJlZUpzTWVhc3VyaW5nKCkpIHtcbiAgICAgICAgICB0aGlzLnZpZXdlclNlcnZpY2UuYWN0aW9uX3Rvb2xib3hfY2FuY2VsX21lc3VyZSgpO1xuICAgICAgICB9IGVsc2UgaWYgKGFsaWduaW5nKSB7XG4gICAgICAgICAgdGhpcy52aWV3ZXJTZXJ2aWNlLmNhbmNlbFRocmVlSnNUYWdBbGlnbm1lbnQoKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB0aGlzLnZpZXdlclNlcnZpY2UuY2FuY2VsVGhyZWVKc1RhZ1BsYWNlbWVudCgpO1xuICAgICAgICB9XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAnY2FsaWJyYXRpb24tdW5kbyc6XG4gICAgICAgIC8vIEN0cmwrWiBvciBCYWNrc3BhY2UgaW4gdGhlIHBhZ2UsIGFzIGluIHRoZSBzY2VuZS5cbiAgICAgICAgdGhpcy52aWV3ZXJTZXJ2aWNlLnVuZG9UaHJlZUpzQWxpZ25tZW50U3RlcCgpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJ21lYXN1cmUtcG9pbnQnOlxuICAgICAgICB0aGlzLnZpZXdlclNlcnZpY2UuYWRkVGhyZWVKc01lYXN1cmVQb2ludEF0TW9kZWxQb2ludChtZXNzYWdlLnBvc2l0aW9uKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICd0YWdDbGljayc6XG4gICAgICAgIGlmIChhbGlnbmluZykge1xuICAgICAgICAgIC8vIENhbGlicmF0aW5nOiBhIHRhZyBjbGlja2VkIGlzIHRoZSBvbmUgdG8gbWF0Y2gsIGFzIGluIHRoZSBzY2VuZSwgYW5kIG9wZW5zIG5vdGhpbmcuXG4gICAgICAgICAgaWYgKHRoaXMuYWxpZ25tZW50Py5hd2FpdGluZyAhPT0gJ3RhZycgfHwgIXRoaXMudmlld2VyU2VydmljZS5zZWxlY3RUaHJlZUpzQWxpZ25tZW50VGFnKG1lc3NhZ2UuaWQpKSB7XG4gICAgICAgICAgICB0aGlzLnZpZXdlclNlcnZpY2UuaWdub3JlVGhyZWVKc0FsaWdubWVudENsaWNrKCd0YWcnKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy52aWV3ZXJTZXJ2aWNlLmNsaWNrVGhyZWVKc1RhZyhtZXNzYWdlLmlkKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICdzbmFwc2hvdCc6XG4gICAgICAgIHRoaXMuc25hcHNob3RzLmdldChtZXNzYWdlLmlkKT8uKG1lc3NhZ2UuaW1hZ2UgPz8gbnVsbCk7XG4gICAgICAgIHRoaXMuc25hcHNob3RzLmRlbGV0ZShtZXNzYWdlLmlkKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICdzaWduJzoge1xuICAgICAgICAvLyBBIHBpZWNlIG9mIHRoZSBTdHJlYW1lZCBTT0cgb3BlbiwgYnkgaXRzIG5hbWUgYmVzaWRlIGxvZC1tZXRhLmpzb24uXG4gICAgICAgIGNvbnN0IGtleSA9IHRoaXMubG9hZGVkS2V5O1xuICAgICAgICBjb25zdCBmb2xkZXIgPSBrZXkgPyBrZXkuc2xpY2UoMCwga2V5Lmxhc3RJbmRleE9mKCcvJykgKyAxKSA6ICcnO1xuICAgICAgICBjb25zdCBmaWxlID0gU3RyaW5nKG1lc3NhZ2UuZmlsZSA/PyAnJyk7XG4gICAgICAgIGNvbnN0IGFsbG93ZWQgPSBrZXkgJiYgaXNTdHJlYW1lZFNwbGF0RmlsZShrZXkpICYmIC9eW1xcdy4tXSskLy50ZXN0KGZpbGUpO1xuICAgICAgICAoYWxsb3dlZCA/IGdldFNpZ25lZEZpbGUoZm9sZGVyICsgZmlsZSkgOiBQcm9taXNlLnJlc29sdmUobnVsbCkpLnRoZW4oKHVybCkgPT4ge1xuICAgICAgICAgIHRoaXMucG9zdCh7IHR5cGU6ICdzaWduZWQnLCBpZDogbWVzc2FnZS5pZCwgdXJsIH0pO1xuICAgICAgICB9KTtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgICBkZWZhdWx0OlxuICAgICAgICBicmVhaztcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGxvYWQoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3Qga2V5ID0gdGhpcy5tb2RlbEtleTtcbiAgICBpZiAoIWtleSB8fCBrZXkgPT09IHRoaXMubG9hZGVkS2V5KSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIHRoaXMubG9hZGVkS2V5ID0ga2V5O1xuICAgIHRoaXMubG9hZFByb2dyZXNzLmVtaXQoMCk7XG4gICAgbGV0IHVybCA9IGtleS5zdGFydHNXaXRoKCdhc3NldHMvJykgPyBrZXkgOiBhd2FpdCBnZXRTaWduZWRGaWxlKGtleSk7XG4gICAgaWYgKHVybCAmJiBpc1N0cmVhbWVkU3BsYXRGaWxlKGtleSkpIHtcbiAgICAgIHVybCA9IGF3YWl0IHRoaXMuc3RyZWFtZWRFbnRyeSh1cmwpO1xuICAgIH1cbiAgICBpZiAodGhpcy5sb2FkZWRLZXkgIT09IGtleSkge1xuICAgICAgLy8gQW5vdGhlciBtb2RlbCB3YXMgYXNrZWQgZm9yLCBvciB0aGUgbG9hZCBjYW5jZWxsZWQsIHdoaWxlIHRoZSBsaW5rIHdhcyBiZWluZyBzaWduZWQuXG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIHRoaXMucG9zdCh7IHR5cGU6ICdsb2FkJywgdXJsLCBmaWxlTmFtZToga2V5LnNwbGl0KCcvJykucG9wKCksIHVwOiB0aGlzLnVwIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIFRoZSBsb2QtbWV0YS5qc29uIG9mIGEgU3RyZWFtZWQgU09HLCB3aXRoIGl0cyBwaWVjZXMgbmFtZWQgc28gdGhhdCB0aGUgcGFnZSBhc2tzIGZvciBlYWNoIG9mXG4gICAqIHRoZW0gd2hlbiBpdCBuZWVkcyBpdCAoJ3NpZ24nKS5cbiAgICpcbiAgICogVGhlIHBpZWNlcyBzaXQgYmVzaWRlIGxvZC1tZXRhLmpzb24gaW4gUzMgYW5kIGFyZSBuYW1lZCByZWxhdGl2ZSB0byBpdCwgd2hpY2ggYSBzaWduZWQgbGluayAtXG4gICAqIGl0cyBzaWduYXR1cmUgaW4gdGhlIHF1ZXJ5IC0gZG9lcyBub3Qgc3Vydml2ZS4gQW5kIHRoZXkgYXJlIGZldGNoZWQgd2hpbGUgdGhlIHZpc2l0IGxhc3RzLCBhcyB0aGVcbiAgICogY2FtZXJhIHJlYWNoZXMgdGhlbSwgbG9uZyBhZnRlciBhbnkgbGluayBzaWduZWQgdXAgZnJvbnQgaGFzIHJ1biBvdXQuXG4gICAqL1xuICBwcml2YXRlIGFzeW5jIHN0cmVhbWVkRW50cnkoc2lnbmVkTWV0YTogc3RyaW5nKTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgICBjb25zdCBtZXRhID0gYXdhaXQgKGF3YWl0IGZldGNoKHNpZ25lZE1ldGEpKS5qc29uKCk7XG4gICAgbWV0YS5maWxlbmFtZXMgPSAobWV0YS5maWxlbmFtZXMgPz8gW10pLm1hcCgobmFtZTogc3RyaW5nKSA9PiBgaHR0cHM6Ly9zcGxhdC5pbnZhbGlkLyR7bmFtZX1gKTtcbiAgICBpZiAodGhpcy5zdHJlYW1lZE1ldGEpIHtcbiAgICAgIFVSTC5yZXZva2VPYmplY3RVUkwodGhpcy5zdHJlYW1lZE1ldGEpO1xuICAgIH1cbiAgICB0aGlzLnN0cmVhbWVkTWV0YSA9IFVSTC5jcmVhdGVPYmplY3RVUkwobmV3IEJsb2IoW0pTT04uc3RyaW5naWZ5KG1ldGEpXSwgeyB0eXBlOiAnYXBwbGljYXRpb24vanNvbicgfSkpO1xuICAgIHJldHVybiB0aGlzLnN0cmVhbWVkTWV0YTtcbiAgfVxuXG4gIHByaXZhdGUgcG9zdFRhZ3MoKTogdm9pZCB7XG4gICAgY29uc3QgeyB0YWdzLCBhbGlnbm1lbnQgfSA9IHRoaXMudmlld2VyU2VydmljZS5nZXRUaHJlZUpzVGFnU25hcHNob3QoKTtcbiAgICAvLyBUYWdzIHBsYWNlZCBlbHNld2hlcmUgLSBpbiBNYXR0ZXJwb3J0LCBpbiBhbm90aGVyIG1vZGVsIC0gYXJlIGluIHRoYXQgcGxhY2UncyBjb29yZGluYXRlcyxcbiAgICAvLyBhbmQgb25seSBhIGNhbGlicmF0aW9uIHNheXMgd2hlcmUgdGhleSBhcmUgaW4gdGhpcyBvbmUuIFdpdGhvdXQgaXQgdGhleSBmbG9hdCBvZmYgdGhlIG1vZGVsXG4gICAgLy8gYW5kIHNlZW0gdG8gc2xpZGUgYXMgdGhlIGNhbWVyYSBtb3ZlczogdGhleSBhcmUgbGVmdCBvdXQgdW50aWwgaXQgaXMgY2FsaWJyYXRlZC4gQVxuICAgIC8vIGNhbGlicmF0aW9uIHVuZGVyIHdheSwgb3IgaXRzIHBhbmVsIG9wZW4sIHNob3dzIHRoZW0gYWxsOiB0aGV5IGFyZSB3aGF0IGl0IG1hdGNoZXMuXG4gICAgY29uc3QgYWxsID0gdGhpcy52aWV3ZXJTZXJ2aWNlLmlzVGhyZWVKc0NhbGlicmF0ZWQoKSB8fCB0aGlzLnZpZXdlclNlcnZpY2UuaXNUaHJlZUpzU2hvd2luZ0NhbGlicmF0aW9uVGFncygpO1xuICAgIGNvbnN0IHNob3duID0gYWxsID8gdGFncyA6IHRhZ3MuZmlsdGVyKCh0YWcpID0+IHRhZy5pbk1vZGVsRnJhbWUpO1xuICAgIHRoaXMucG9zdCh7XG4gICAgICB0eXBlOiAndGFncycsXG4gICAgICB0YWdzOiBzaG93bi5tYXAoKHsgaWQsIHBvc2l0aW9uLCBsYWJlbCwgaWNvblVybCwgaW5Nb2RlbEZyYW1lLCBub3JtYWwgfSkgPT4gKHsgaWQsIHBvc2l0aW9uLCBsYWJlbCwgaWNvblVybCwgaW5Nb2RlbEZyYW1lLCBub3JtYWwgfSkpLFxuICAgICAgYWxpZ25tZW50LFxuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIFRoZSBjYWxpYnJhdGlvbiB1bmRlciB3YXksIGZvciB0aGUgcGFnZSB0byBkcmF3IC0gdGhlIHBpbnMgZHJvcHBlZCwgdGhlIHRhZyBiZWluZyBtYXRjaGVkIC0gYW5kLFxuICAgKiB3aGlsZSB0aGUgcGxhY2Ugb2YgYSB0YWcgaXMgYXNrZWQgZm9yLCB0byB0YWtlIHRoZSBjbGljayBvbiB0aGUgbW9kZWwgdGhhdCBzYXlzIHdoZXJlICgncGlja2VkJykuXG4gICAqL1xuICBwcml2YXRlIHBvc3RDYWxpYnJhdGlvbigpOiB2b2lkIHtcbiAgICBjb25zdCBvbiA9IHRoaXMudmlld2VyU2VydmljZS5pc1RocmVlSnNBbGlnbmluZ1RhZ3MoKSAmJiAhIXRoaXMuYWxpZ25tZW50O1xuICAgIGNvbnN0IGF3YWl0aW5nID0gb24gPyB0aGlzLmFsaWdubWVudCEuYXdhaXRpbmcgOiBudWxsO1xuICAgIHRoaXMucG9zdCh7XG4gICAgICB0eXBlOiAnY2FsaWJyYXRpb24nLFxuICAgICAgY2FsaWJyYXRpb246IG9uXG4gICAgICAgID8ge1xuICAgICAgICAgIHNlbGVjdGVkOiBhd2FpdGluZyA9PT0gJ3BvaW50JyA/IHRoaXMuYWxpZ25tZW50IS50YWdJZCA/PyBudWxsIDogbnVsbCxcbiAgICAgICAgICBwYWlyczogdGhpcy5hbGlnbm1lbnQhLm1hdGNoZWQubWFwKCh7IHRhZ0lkLCB0YXJnZXQgfSkgPT4gKHsgdGFnSWQsIHRhcmdldCB9KSksXG4gICAgICAgIH1cbiAgICAgICAgOiBudWxsLFxuICAgIH0pO1xuICAgIGNvbnN0IHBpY2tpbmcgPSBhd2FpdGluZyA9PT0gJ3BvaW50JztcbiAgICAvLyBPbmx5IHdoZW4gaXQgY2hhbmdlczogcGxhY2luZyBhIHRhZyB1c2VzIHRoZSBzYW1lIGNsaWNrLCBhbmQgaXMgbm90IHRvIGJlIHN3aXRjaGVkIG9mZiBoZXJlLlxuICAgIGlmIChwaWNraW5nICE9PSB0aGlzLnBpY2tpbmdGb3JDYWxpYnJhdGlvbikge1xuICAgICAgdGhpcy5waWNraW5nRm9yQ2FsaWJyYXRpb24gPSBwaWNraW5nO1xuICAgICAgdGhpcy5wb3N0KHsgdHlwZTogJ3BsYWNpbmcnLCBvbjogcGlja2luZyB9KTtcbiAgICB9XG4gIH1cblxuICAvKiogVGhlIG1lYXN1cmVtZW50IGZvciB0aGUgcGFnZSB0byBkcmF3IC0gaXRzIHBvaW50cywgZWFjaCBzZWdtZW50J3MgbGVuZ3RoIC0gb3Igbm90aGluZy4gKi9cbiAgcHJpdmF0ZSBwb3N0TWVhc3VyZW1lbnQoZHJhd246IGJvb2xlYW4pOiB2b2lkIHtcbiAgICB0aGlzLnBvc3Qoe1xuICAgICAgdHlwZTogJ21lYXN1cmVtZW50JyxcbiAgICAgIG1lYXN1cmVtZW50OiBkcmF3blxuICAgICAgICA/IHsgcG9pbnRzOiB0aGlzLnZpZXdlclNlcnZpY2UuZ2V0VGhyZWVKc01lYXN1cmVQb2ludHNJbk1vZGVsRnJhbWUoKSwgZGlzdGFuY2VzOiB0aGlzLm1lYXN1cmVEaXN0YW5jZXMgfVxuICAgICAgICA6IG51bGwsXG4gICAgfSk7XG4gIH1cblxuICBwcml2YXRlIHBvc3QoY29tbWFuZDogb2JqZWN0KTogdm9pZCB7XG4gICAgY29uc3QgcGFnZSA9IHRoaXMuZnJhbWU/Lm5hdGl2ZUVsZW1lbnQuY29udGVudFdpbmRvdztcbiAgICBpZiAocGFnZSAmJiB0aGlzLnJlYWR5KSB7XG4gICAgICBwYWdlLnBvc3RNZXNzYWdlKGNvbW1hbmQsIHdpbmRvdy5sb2NhdGlvbi5vcmlnaW4pO1xuICAgIH1cbiAgfVxufVxuIl19
|