@smarterplan/ngx-smarterplan-core 1.4.5 → 1.4.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.
- package/esm2022/lib/helpers.service.mjs +27 -20
- package/esm2022/lib/mattertagData.mjs +84 -84
- package/esm2022/lib/pipes/time-date-to-local-string.pipe.mjs +3 -8
- package/esm2022/lib/services/locale.service.mjs +3 -5
- package/esm2022/lib/services/matterport-import.service.mjs +3 -3
- package/esm2022/lib/services/matterport-measurement.service.mjs +78 -0
- package/esm2022/lib/services/matterport-navigation.service.mjs +157 -0
- package/esm2022/lib/services/matterport-object3d.service.mjs +234 -0
- package/esm2022/lib/services/matterport-pointer.service.mjs +130 -0
- package/esm2022/lib/services/matterport-tag.service.mjs +458 -0
- package/esm2022/lib/services/matterport.service.mjs +427 -988
- package/esm2022/lib/services/models/equipment.service.mjs +3 -4
- package/esm2022/lib/services/models/feature.service.mjs +3 -3
- package/esm2022/lib/services/models/measurement.service.mjs +3 -3
- package/esm2022/lib/services/models/ticket.service.mjs +3 -4
- package/esm2022/lib/services/navigator.service.mjs +10 -2
- package/esm2022/lib/services/tag.service.mjs +45 -19
- package/esm2022/lib/services/viewer.service.mjs +51 -16
- package/esm2022/lib/types.service.mjs +1 -1
- package/fesm2022/smarterplan-ngx-smarterplan-core.mjs +2028 -1490
- package/fesm2022/smarterplan-ngx-smarterplan-core.mjs.map +1 -1
- package/lib/helpers.service.d.ts +6 -0
- package/lib/mattertagData.d.ts +52 -10
- package/lib/services/matterport-measurement.service.d.ts +35 -0
- package/lib/services/matterport-navigation.service.d.ts +38 -0
- package/lib/services/matterport-object3d.service.d.ts +31 -0
- package/lib/services/matterport-pointer.service.d.ts +31 -0
- package/lib/services/matterport-tag.service.d.ts +104 -0
- package/lib/services/matterport.service.d.ts +91 -92
- package/lib/services/models/equipment.service.d.ts +2 -2
- package/lib/services/models/feature.service.d.ts +2 -2
- package/lib/services/models/measurement.service.d.ts +2 -2
- package/lib/services/models/ticket.service.d.ts +2 -2
- package/lib/services/tag.service.d.ts +4 -0
- package/lib/services/viewer.service.d.ts +1 -1
- package/lib/types.service.d.ts +2 -0
- package/package.json +21 -1
- package/esm2022/lib/matterport-extensions/hsl-loader/HlsLoader.mjs +0 -66
- package/esm2022/lib/matterport-extensions/video-renderer/VideoRenderer.mjs +0 -63
- package/lib/matterport-extensions/hsl-loader/HlsLoader.d.ts +0 -26
- package/lib/matterport-extensions/video-renderer/VideoRenderer.d.ts +0 -26
|
@@ -0,0 +1,458 @@
|
|
|
1
|
+
import { isDevMode, Injectable } from '@angular/core';
|
|
2
|
+
import { Subject } from 'rxjs';
|
|
3
|
+
import { MattertagData } from '../mattertagData';
|
|
4
|
+
import { TagAction, CameraMode } from '../types.service';
|
|
5
|
+
import { wait } from '../helpers.service';
|
|
6
|
+
import * as i0 from "@angular/core";
|
|
7
|
+
import * as i1 from "./matterport-navigation.service";
|
|
8
|
+
export class MatterportTagService {
|
|
9
|
+
navigationService;
|
|
10
|
+
dictionnaryTags = new Map();
|
|
11
|
+
tagAddQueue = Promise.resolve();
|
|
12
|
+
mattertagToFollow = null;
|
|
13
|
+
onGoToTag = new Subject();
|
|
14
|
+
mattertagIDs = [];
|
|
15
|
+
tagsAttachments = {};
|
|
16
|
+
tagMessengerOn = false;
|
|
17
|
+
tagService = null;
|
|
18
|
+
tagsCurrentOpacity = new Map();
|
|
19
|
+
tagsCurrentEnabled = new Map();
|
|
20
|
+
constructor(navigationService) {
|
|
21
|
+
this.navigationService = navigationService;
|
|
22
|
+
}
|
|
23
|
+
setTagService(service) {
|
|
24
|
+
this.tagService = service;
|
|
25
|
+
}
|
|
26
|
+
/** Opens a specific tag in the Matterport viewer by its ID. */
|
|
27
|
+
async goToTag(sdk, sid) {
|
|
28
|
+
if (!sdk)
|
|
29
|
+
return;
|
|
30
|
+
try {
|
|
31
|
+
this.onGoToTag.next(sid);
|
|
32
|
+
await sdk.Tag.open(sid);
|
|
33
|
+
}
|
|
34
|
+
catch (e) {
|
|
35
|
+
if (isDevMode())
|
|
36
|
+
console.warn('Cannot open tag', sid, e);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
/** Opens the most recently created tag in the viewer. */
|
|
40
|
+
async goToLastTag(sdk) {
|
|
41
|
+
if (!sdk || this.mattertagIDs.length === 0)
|
|
42
|
+
return;
|
|
43
|
+
const lastSid = this.mattertagIDs[this.mattertagIDs.length - 1];
|
|
44
|
+
return this.goToTag(sdk, lastSid);
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Adds a Mattertag to the viewer, serializing calls to prevent SDK race conditions.
|
|
48
|
+
* Reuses existing IDs if the tag is already present in the session.
|
|
49
|
+
*/
|
|
50
|
+
async addMattertagToViewer(sdk, mattertagData) {
|
|
51
|
+
if (!sdk)
|
|
52
|
+
return null;
|
|
53
|
+
this.tagAddQueue = this.tagAddQueue.then(async () => {
|
|
54
|
+
const data = mattertagData.getData();
|
|
55
|
+
const existingId = data?.id || null;
|
|
56
|
+
try {
|
|
57
|
+
const sidList = await sdk.Tag.add(data);
|
|
58
|
+
if (sidList && sidList.length > 0) {
|
|
59
|
+
const mattertagID = sidList[0];
|
|
60
|
+
this.mattertagIDs.push(mattertagID);
|
|
61
|
+
this.dictionnaryTags.set(mattertagID, mattertagData);
|
|
62
|
+
return mattertagID;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
catch (error) {
|
|
66
|
+
if (error?.message?.includes('already in use') && existingId) {
|
|
67
|
+
if (!this.dictionnaryTags.has(existingId)) {
|
|
68
|
+
this.mattertagIDs.push(existingId);
|
|
69
|
+
this.dictionnaryTags.set(existingId, mattertagData);
|
|
70
|
+
}
|
|
71
|
+
return existingId;
|
|
72
|
+
}
|
|
73
|
+
if (isDevMode())
|
|
74
|
+
console.warn('Failed to add tag to viewer', error);
|
|
75
|
+
}
|
|
76
|
+
return null;
|
|
77
|
+
});
|
|
78
|
+
return this.tagAddQueue;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Internal method to add and configure a Mattertag with icon, opacity, and HTML content.
|
|
82
|
+
* Handles existing tags gracefully and queues operations to avoid SDK conflicts.
|
|
83
|
+
*/
|
|
84
|
+
async _doAddMattertag(sdk, mattertagData, setTagIconAndOpacity, injectHtmlInTag) {
|
|
85
|
+
const descriptor = mattertagData.getMattertagDescriptor();
|
|
86
|
+
//console.log('descriptor', descriptor);
|
|
87
|
+
const sid = descriptor[0]['id'];
|
|
88
|
+
if (sid && this.dictionnaryTags.has(sid)) {
|
|
89
|
+
await setTagIconAndOpacity(sid, mattertagData);
|
|
90
|
+
await injectHtmlInTag(mattertagData.getType(), mattertagData.getObject(), sid);
|
|
91
|
+
return sid;
|
|
92
|
+
}
|
|
93
|
+
this.tagAddQueue = this.tagAddQueue.then(async () => {
|
|
94
|
+
try {
|
|
95
|
+
const [createdSid] = await sdk.Tag.add(...descriptor);
|
|
96
|
+
this.mattertagIDs.push(createdSid);
|
|
97
|
+
this.dictionnaryTags.set(createdSid, mattertagData);
|
|
98
|
+
await wait(100);
|
|
99
|
+
await setTagIconAndOpacity(createdSid, mattertagData);
|
|
100
|
+
injectHtmlInTag(mattertagData.getType(), mattertagData.getObject(), createdSid).catch(err => {
|
|
101
|
+
if (isDevMode())
|
|
102
|
+
console.warn('HTML injection failed for', createdSid, err);
|
|
103
|
+
});
|
|
104
|
+
return createdSid;
|
|
105
|
+
}
|
|
106
|
+
catch (e) {
|
|
107
|
+
if (e?.message?.includes('already in use') && sid) {
|
|
108
|
+
if (!this.dictionnaryTags.has(sid)) {
|
|
109
|
+
this.mattertagIDs.push(sid);
|
|
110
|
+
this.dictionnaryTags.set(sid, mattertagData);
|
|
111
|
+
}
|
|
112
|
+
await setTagIconAndOpacity(sid, mattertagData);
|
|
113
|
+
await injectHtmlInTag(mattertagData.getType(), mattertagData.getObject(), sid);
|
|
114
|
+
return sid;
|
|
115
|
+
}
|
|
116
|
+
throw e;
|
|
117
|
+
}
|
|
118
|
+
});
|
|
119
|
+
return this.tagAddQueue;
|
|
120
|
+
}
|
|
121
|
+
getDistance(p1, p2) {
|
|
122
|
+
return Math.sqrt(Math.pow(p2.x - p1.x, 2) + Math.pow(p2.y - p1.y, 2) + Math.pow(p2.z - p1.z, 2));
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Checks if a tag is within the bounding box of any active room (adding a slight margin to account for wall-mounted tags).
|
|
126
|
+
* If there are no active rooms (e.g., hallway), falls back to returning true.
|
|
127
|
+
*/
|
|
128
|
+
isTagInRooms(mattertagData, rooms) {
|
|
129
|
+
if (!rooms || rooms.length === 0)
|
|
130
|
+
return false;
|
|
131
|
+
const tagPos = mattertagData.getPosition();
|
|
132
|
+
const margin = 1.5;
|
|
133
|
+
return rooms.some((room) => {
|
|
134
|
+
if (!room.bounds)
|
|
135
|
+
return false;
|
|
136
|
+
const { min, max } = room.bounds;
|
|
137
|
+
return (tagPos.x >= min.x - margin && tagPos.x <= max.x + margin &&
|
|
138
|
+
tagPos.y >= min.y - margin && tagPos.y <= max.y + margin &&
|
|
139
|
+
tagPos.z >= min.z - margin && tagPos.z <= max.z + margin);
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Computes the final context-aware opacity for a single tag.
|
|
144
|
+
* @param currentFloorSequence Authoritative current floor sequence from sdk.Floor.current
|
|
145
|
+
* (null = single-floor model or unknown).
|
|
146
|
+
* @param currentRooms Array of active rooms the camera is in.
|
|
147
|
+
*/
|
|
148
|
+
/*computeSingleTagContextOpacity(
|
|
149
|
+
mattertagData: MattertagData,
|
|
150
|
+
poseCamera: any,
|
|
151
|
+
sweepCollection: any,
|
|
152
|
+
currentFloorSequence: number | null,
|
|
153
|
+
currentRooms: any[]
|
|
154
|
+
): number {
|
|
155
|
+
const mode = this.navigationService.currentCameraMode;
|
|
156
|
+
|
|
157
|
+
// 1. Check Floor
|
|
158
|
+
const tagFloorId = this.getFloorIdForTag(mattertagData, sweepCollection);
|
|
159
|
+
const currentFloorId = currentFloorSequence?.toString();
|
|
160
|
+
if (tagFloorId && currentFloorId && tagFloorId !== currentFloorId) {
|
|
161
|
+
return 0;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
// 2. Si Dollhouse -> Pleine opacité
|
|
165
|
+
//if (mode !== CameraMode.INSIDE) return 1;
|
|
166
|
+
|
|
167
|
+
// 3. Si Inside -> Check pièce + Distance progressive
|
|
168
|
+
//if (!this.isTagInRooms(mattertagData, currentRooms)) return 0;
|
|
169
|
+
|
|
170
|
+
return 1;
|
|
171
|
+
}*/
|
|
172
|
+
/** Returns the ID of the most recently added tag. */
|
|
173
|
+
getLastTag() {
|
|
174
|
+
if (this.mattertagIDs.length === 0)
|
|
175
|
+
return null;
|
|
176
|
+
return this.mattertagIDs[this.mattertagIDs.length - 1];
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Updates the visibility (opacity) of all tags based on the current camera mode,
|
|
180
|
+
* floor and room context. Must be called after each sweep, floor or mode change.
|
|
181
|
+
*
|
|
182
|
+
* Rules:
|
|
183
|
+
* - DOLLHOUSE / FLOORPLAN → all tags hidden (opacity 0).
|
|
184
|
+
* - INSIDE → only tags whose sweep belongs to the current floor are shown;
|
|
185
|
+
* proximity-based opacity is applied via computeTagOpacity().
|
|
186
|
+
* Tags on other floors are hidden (opacity 0).
|
|
187
|
+
* - TRANSITIONING → no change (skip update to avoid flickering).
|
|
188
|
+
*
|
|
189
|
+
* @param sdk Matterport SDK instance.
|
|
190
|
+
* @param poseCamera Current camera pose.
|
|
191
|
+
* @param sweepCollection Full collection of sweeps.
|
|
192
|
+
* @param currentCameraMode Current camera mode.
|
|
193
|
+
* @param mattertagToFollow ID of the cursor tag (never touched).
|
|
194
|
+
*/
|
|
195
|
+
async updateTagsVisibilityForContext(sdk, sweepCollection, currentCameraMode, mattertagToFollow, currentFloorSequence = null, currentRooms = []) {
|
|
196
|
+
if (!sdk || this.dictionnaryTags.size === 0)
|
|
197
|
+
return;
|
|
198
|
+
const isInteriorMode = currentCameraMode === CameraMode.INSIDE;
|
|
199
|
+
const currentFloorId = currentFloorSequence !== null ? currentFloorSequence.toString() : null;
|
|
200
|
+
const promises = [];
|
|
201
|
+
for (const [tagId, mattertagData] of this.dictionnaryTags) {
|
|
202
|
+
if (tagId === mattertagToFollow)
|
|
203
|
+
continue;
|
|
204
|
+
const tagFloorId = this.getFloorIdForTag(mattertagData, sweepCollection);
|
|
205
|
+
const isOnCurrentFloor = !tagFloorId || !currentFloorId || tagFloorId === currentFloorId;
|
|
206
|
+
let targetOpacity = 0;
|
|
207
|
+
let shouldBeEnabled = false;
|
|
208
|
+
// Calculation of opacity and enable status
|
|
209
|
+
if (isOnCurrentFloor) {
|
|
210
|
+
if (!isInteriorMode) {
|
|
211
|
+
targetOpacity = 1;
|
|
212
|
+
shouldBeEnabled = true;
|
|
213
|
+
}
|
|
214
|
+
else {
|
|
215
|
+
targetOpacity = 0.9;
|
|
216
|
+
shouldBeEnabled = true;
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
// Apply changes
|
|
220
|
+
// Tooltip and click management
|
|
221
|
+
const lastEnabled = this.tagsCurrentEnabled.get(tagId);
|
|
222
|
+
if (lastEnabled !== shouldBeEnabled) {
|
|
223
|
+
this.tagsCurrentEnabled.set(tagId, shouldBeEnabled);
|
|
224
|
+
promises.push(sdk.Tag.allowAction(tagId, {
|
|
225
|
+
opening: shouldBeEnabled,
|
|
226
|
+
navigating: shouldBeEnabled,
|
|
227
|
+
docking: false
|
|
228
|
+
}).catch(() => { }));
|
|
229
|
+
}
|
|
230
|
+
// Opacity management
|
|
231
|
+
const lastOpacity = this.tagsCurrentOpacity.get(tagId) ?? -1;
|
|
232
|
+
if (Math.abs(lastOpacity - targetOpacity) > 0.05) {
|
|
233
|
+
this.tagsCurrentOpacity.set(tagId, targetOpacity);
|
|
234
|
+
promises.push(sdk.Tag.editOpacity(tagId, targetOpacity).catch(() => { }));
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
await Promise.all(promises);
|
|
238
|
+
}
|
|
239
|
+
/** Removes a specific tag from the viewer and local dictionaries. */
|
|
240
|
+
async deleteMattertagFromId(sdk, mattertagID) {
|
|
241
|
+
try {
|
|
242
|
+
if (sdk)
|
|
243
|
+
await sdk.Tag.remove(mattertagID);
|
|
244
|
+
this.dictionnaryTags.delete(mattertagID);
|
|
245
|
+
const index = this.mattertagIDs.indexOf(mattertagID);
|
|
246
|
+
if (index > -1)
|
|
247
|
+
this.mattertagIDs.splice(index, 1);
|
|
248
|
+
}
|
|
249
|
+
catch (e) {
|
|
250
|
+
if (isDevMode())
|
|
251
|
+
console.warn('Cannot delete tag', mattertagID, e);
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
/** Removes the last added tag from the viewer. */
|
|
255
|
+
async deleteLastMattertag(sdk) {
|
|
256
|
+
const lastSid = this.getLastTag();
|
|
257
|
+
if (lastSid)
|
|
258
|
+
await this.deleteMattertagFromId(sdk, lastSid);
|
|
259
|
+
}
|
|
260
|
+
/** Clears all tags from the viewer and resets local state. */
|
|
261
|
+
async action_delete_all_mattertags(sdk) {
|
|
262
|
+
if (sdk) {
|
|
263
|
+
const sidsToRemove = [...this.mattertagIDs];
|
|
264
|
+
for (const sid of sidsToRemove) {
|
|
265
|
+
try {
|
|
266
|
+
await sdk.Tag.remove(sid);
|
|
267
|
+
}
|
|
268
|
+
catch (e) { }
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
this.clear();
|
|
272
|
+
}
|
|
273
|
+
/**
|
|
274
|
+
* Creates and configures a Mattertag from a POI, handling coordinates, normals, and sweep ID.
|
|
275
|
+
* Skips creation if a tag for the object already exists.
|
|
276
|
+
*/
|
|
277
|
+
async createMattertagFromPOI(sdk, tagType, object, poi, poseCamera, getTagFromElementId, setTagIconAndOpacity, injectHtmlInTag) {
|
|
278
|
+
const { tag } = getTagFromElementId(object.id);
|
|
279
|
+
if (tag)
|
|
280
|
+
return;
|
|
281
|
+
const mattertagData = new MattertagData(tagType);
|
|
282
|
+
mattertagData.setObject(object, tagType);
|
|
283
|
+
if (poi.coordinate) {
|
|
284
|
+
try {
|
|
285
|
+
mattertagData.setPosition(JSON.parse(poi.coordinate));
|
|
286
|
+
}
|
|
287
|
+
catch (e) {
|
|
288
|
+
if (isDevMode())
|
|
289
|
+
console.warn('Error parsing POI coordinates', poi.coordinate);
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
if (poi.metadata) {
|
|
293
|
+
try {
|
|
294
|
+
const tagMetadata = JSON.parse(poi.metadata);
|
|
295
|
+
mattertagData.setNormal(tagMetadata.normal || { x: 0, y: -0.15, z: 0 });
|
|
296
|
+
}
|
|
297
|
+
catch (e) {
|
|
298
|
+
mattertagData.setNormal({ x: 0, y: -0.15, z: 0 });
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
if (poi.matterportSweepID) {
|
|
302
|
+
mattertagData.setSweepID(poi.matterportSweepID);
|
|
303
|
+
}
|
|
304
|
+
mattertagData.setPoi(poi);
|
|
305
|
+
const createdTagID = await this.addMattertagToViewer(sdk, mattertagData);
|
|
306
|
+
if (createdTagID && sdk) {
|
|
307
|
+
await wait(100);
|
|
308
|
+
await setTagIconAndOpacity(createdTagID, mattertagData);
|
|
309
|
+
injectHtmlInTag(tagType, object, createdTagID).catch(err => {
|
|
310
|
+
if (isDevMode())
|
|
311
|
+
console.warn('HTML injection failed for', createdTagID, err);
|
|
312
|
+
});
|
|
313
|
+
}
|
|
314
|
+
return createdTagID;
|
|
315
|
+
}
|
|
316
|
+
/** Updates the icon, opacity, and HTML content of an existing tag. */
|
|
317
|
+
async updateMatterTagContentForTagID(sdk, mattertagID, object, poiType, setTagIconAndOpacity, injectHtmlInTag) {
|
|
318
|
+
const mattertagData = this.dictionnaryTags.get(mattertagID);
|
|
319
|
+
if (!mattertagData)
|
|
320
|
+
return;
|
|
321
|
+
if (object) {
|
|
322
|
+
mattertagData.setObject(object, poiType);
|
|
323
|
+
}
|
|
324
|
+
await setTagIconAndOpacity(mattertagID, mattertagData);
|
|
325
|
+
await injectHtmlInTag(poiType, object, mattertagID);
|
|
326
|
+
}
|
|
327
|
+
/** Registers a custom texture and applies it to a tag, optionally adjusting opacity. */
|
|
328
|
+
async addNewIconAndSetForTag(sdk, mattertagID, iconPath, applyOpacity, opacity) {
|
|
329
|
+
if (!sdk)
|
|
330
|
+
return;
|
|
331
|
+
try {
|
|
332
|
+
const iconName = `custom-icon-${mattertagID}`;
|
|
333
|
+
await sdk.Asset.registerTexture(iconName, iconPath);
|
|
334
|
+
await sdk.Tag.editIcon(mattertagID, iconName);
|
|
335
|
+
if (applyOpacity) {
|
|
336
|
+
await sdk.Tag.editOpacity(mattertagID, opacity);
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
catch (error) {
|
|
340
|
+
if (isDevMode())
|
|
341
|
+
console.warn('Error setting custom icon or opacity', error);
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
/** Finds the tag ID and sweep ID associated with a specific element ID. */
|
|
345
|
+
getTagFromElementId(elementID, sweeps) {
|
|
346
|
+
let tagID = null;
|
|
347
|
+
let sweepID = null;
|
|
348
|
+
for (let [mattertagID, mattertagData] of this.dictionnaryTags) {
|
|
349
|
+
if (mattertagData.elementID === elementID) {
|
|
350
|
+
tagID = mattertagID;
|
|
351
|
+
const sweep = mattertagData.getSweepID();
|
|
352
|
+
if (sweep && sweeps && sweeps.includes(sweep)) {
|
|
353
|
+
sweepID = sweep;
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
return { tag: tagID, sweep: sweepID };
|
|
358
|
+
}
|
|
359
|
+
/** Retrieves the floor identifier associated with a tag based on its sweep data.
|
|
360
|
+
* Handles both the object form ({ floorInfo: { id, sequence }, floor: { id } })
|
|
361
|
+
* and the primitive form (floor: number) used by Matterport SDK v3.
|
|
362
|
+
*/
|
|
363
|
+
getFloorIdForTag(mattertagData, sweepCollection) {
|
|
364
|
+
const sweepId = mattertagData.getSweepID();
|
|
365
|
+
if (!sweepId || !sweepCollection)
|
|
366
|
+
return null;
|
|
367
|
+
const sweepData = sweepCollection[sweepId];
|
|
368
|
+
if (!sweepData)
|
|
369
|
+
return null;
|
|
370
|
+
// SDK v3: sweep.floor is a primitive number (the sequence index)
|
|
371
|
+
if (typeof sweepData.floor === 'number') {
|
|
372
|
+
return sweepData.floor.toString();
|
|
373
|
+
}
|
|
374
|
+
// Older / extended formats
|
|
375
|
+
return sweepData?.floorInfo?.id
|
|
376
|
+
?? sweepData?.floorInfo?.sequence?.toString()
|
|
377
|
+
?? sweepData?.floorId
|
|
378
|
+
?? sweepData?.floor?.id
|
|
379
|
+
?? sweepData?.floor?.sequence?.toString()
|
|
380
|
+
?? null;
|
|
381
|
+
}
|
|
382
|
+
/**
|
|
383
|
+
* Injects custom HTML or fallback billboard media into a Mattertag sandbox.
|
|
384
|
+
* Attaches event listeners for interactive elements within the tag.
|
|
385
|
+
*/
|
|
386
|
+
async injectHtmlInTag(sdk, tagType, object, tagID) {
|
|
387
|
+
if (!this.tagService) {
|
|
388
|
+
console.error('[MatterportTagService] tagService is not initialized.');
|
|
389
|
+
return;
|
|
390
|
+
}
|
|
391
|
+
try {
|
|
392
|
+
let html = await this.tagService.getHtmlToInject(tagType, object);
|
|
393
|
+
if (html && html.trim().length > 0 && sdk) {
|
|
394
|
+
const scriptTag = this.tagService.getScriptForTag(object, tagType);
|
|
395
|
+
html += `${scriptTag}`;
|
|
396
|
+
const [sandboxId, messenger] = await sdk.Tag.registerSandbox(html);
|
|
397
|
+
const attachmentID = this.tagsAttachments[tagID];
|
|
398
|
+
if (attachmentID) {
|
|
399
|
+
try {
|
|
400
|
+
await sdk.Tag.detach(tagID, attachmentID);
|
|
401
|
+
}
|
|
402
|
+
catch (e) { }
|
|
403
|
+
}
|
|
404
|
+
this.tagsAttachments[tagID] = sandboxId;
|
|
405
|
+
await sdk.Tag.attach(tagID, sandboxId);
|
|
406
|
+
// Attach the "View informations" handler in tooltip
|
|
407
|
+
messenger.on(TagAction.DETAIL_CLICK, this.tagService.onActionDetailClick.bind(this.tagService));
|
|
408
|
+
messenger.on(TagAction.TICKET_CLICK, this.tagService.onActionDetailClick.bind(this.tagService));
|
|
409
|
+
messenger.on(TagAction.AUDIO_CLICK, (audioCommentID) => this.tagService.onActionAudioClick(audioCommentID));
|
|
410
|
+
messenger.on(TagAction.VIDEO_CLICK, (videoUrl) => this.tagService.onActionVideoClick(videoUrl));
|
|
411
|
+
messenger.on(TagAction.IMAGE_CLICK, (imageCommentID) => this.tagService.onActionImageClick(imageCommentID));
|
|
412
|
+
messenger.on(TagAction.DOC_CLICK, (docUrl) => this.tagService.onActionDocClick(docUrl));
|
|
413
|
+
messenger.on(TagAction.YOUTUBE_CLICK, (youtubeUrl) => this.tagService.onActionYoutubeClick(youtubeUrl));
|
|
414
|
+
}
|
|
415
|
+
else if (sdk) {
|
|
416
|
+
const { comment, tagDescription } = this.tagService.getBillboardMediaToEmbed(object);
|
|
417
|
+
if (comment) {
|
|
418
|
+
const attachmentID = await sdk.Tag.registerAttachment({
|
|
419
|
+
type: 'media',
|
|
420
|
+
data: {
|
|
421
|
+
url: comment.externalLink,
|
|
422
|
+
label: object.title || 'Media',
|
|
423
|
+
},
|
|
424
|
+
});
|
|
425
|
+
await sdk.Tag.attach(tagID, attachmentID);
|
|
426
|
+
const billboardAttachmentID = await sdk.Tag.registerAttachment({
|
|
427
|
+
type: 'billboard',
|
|
428
|
+
data: {
|
|
429
|
+
title: object.title,
|
|
430
|
+
description: tagDescription,
|
|
431
|
+
},
|
|
432
|
+
});
|
|
433
|
+
await sdk.Tag.attach(tagID, billboardAttachmentID);
|
|
434
|
+
this.tagsAttachments[tagID] = billboardAttachmentID;
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
catch (error) {
|
|
439
|
+
console.error('[MatterportTagService] Error in injectHtmlInTag:', error);
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
/** Clears all local tag data and resets the addition queue. */
|
|
443
|
+
clear() {
|
|
444
|
+
this.dictionnaryTags.clear();
|
|
445
|
+
this.tagAddQueue = Promise.resolve();
|
|
446
|
+
this.mattertagToFollow = null;
|
|
447
|
+
this.mattertagIDs = [];
|
|
448
|
+
}
|
|
449
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: MatterportTagService, deps: [{ token: i1.MatterportNavigationService }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
450
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: MatterportTagService, providedIn: 'root' });
|
|
451
|
+
}
|
|
452
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: MatterportTagService, decorators: [{
|
|
453
|
+
type: Injectable,
|
|
454
|
+
args: [{
|
|
455
|
+
providedIn: 'root',
|
|
456
|
+
}]
|
|
457
|
+
}], ctorParameters: () => [{ type: i1.MatterportNavigationService }] });
|
|
458
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWF0dGVycG9ydC10YWcuc2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL25neC1zbWFydGVycGxhbi1jb3JlL3NyYy9saWIvc2VydmljZXMvbWF0dGVycG9ydC10YWcuc2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsU0FBUyxFQUFFLFVBQVUsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUN0RCxPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0sTUFBTSxDQUFDO0FBQy9CLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQztBQUNqRCxPQUFPLEVBQWtELFNBQVMsRUFBRSxVQUFVLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQztBQUV6RyxPQUFPLEVBQUUsSUFBSSxFQUFFLE1BQU0sb0JBQW9CLENBQUM7OztBQU0xQyxNQUFNLE9BQU8sb0JBQW9CO0lBYXJCO0lBWkgsZUFBZSxHQUErQixJQUFJLEdBQUcsRUFBRSxDQUFDO0lBQ3hELFdBQVcsR0FBaUIsT0FBTyxDQUFDLE9BQU8sRUFBRSxDQUFDO0lBQzlDLGlCQUFpQixHQUFrQixJQUFJLENBQUM7SUFDeEMsU0FBUyxHQUFHLElBQUksT0FBTyxFQUFVLENBQUM7SUFDbEMsWUFBWSxHQUFrQixFQUFFLENBQUM7SUFDakMsZUFBZSxHQUFXLEVBQUUsQ0FBQztJQUM3QixjQUFjLEdBQVksS0FBSyxDQUFDO0lBQ2hDLFVBQVUsR0FBMEIsSUFBSSxDQUFDO0lBQ3hDLGtCQUFrQixHQUF3QixJQUFJLEdBQUcsRUFBRSxDQUFDO0lBQ3BELGtCQUFrQixHQUF5QixJQUFJLEdBQUcsRUFBRSxDQUFDO0lBRTdELFlBQ1UsaUJBQThDO1FBQTlDLHNCQUFpQixHQUFqQixpQkFBaUIsQ0FBNkI7SUFDcEQsQ0FBQztJQUVMLGFBQWEsQ0FBQyxPQUF1QjtRQUNuQyxJQUFJLENBQUMsVUFBVSxHQUFHLE9BQU8sQ0FBQztJQUM1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RSxLQUFLLENBQUMsQ0FBQztRQUMzRSxDQUFDO0lBQ0gsQ0FBQztJQUVELCtEQUErRDtJQUMvRCxLQUFLO1FBQ0gsSUFBSSxDQUFDLGVBQWUsQ0FBQyxLQUFLLEVBQUUsQ0FBQztRQUM3QixJQUFJLENBQUMsV0FBVyxHQUFHLE9BQU8sQ0FBQyxPQUFPLEVBQUUsQ0FBQztRQUNyQyxJQUFJLENBQUMsaUJBQWlCLEdBQUcsSUFBSSxDQUFDO1FBQzlCLElBQUksQ0FBQyxZQUFZLEdBQUcsRUFBRSxDQUFDO0lBQ3pCLENBQUM7d0dBdGZVLG9CQUFvQjs0R0FBcEIsb0JBQW9CLGNBRm5CLE1BQU07OzRGQUVQLG9CQUFvQjtrQkFIaEMsVUFBVTttQkFBQztvQkFDVixVQUFVLEVBQUUsTUFBTTtpQkFDbkIiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBpc0Rldk1vZGUsIEluamVjdGFibGUgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcclxuaW1wb3J0IHsgU3ViamVjdCB9IGZyb20gJ3J4anMnO1xyXG5pbXBvcnQgeyBNYXR0ZXJ0YWdEYXRhIH0gZnJvbSAnLi4vbWF0dGVydGFnRGF0YSc7XHJcbmltcG9ydCB7IFBvaVR5cGUsIERiT2JqZWN0VHlwZSwgUE9JLCBWaWV3ZXJJbnRlcmFjdGlvbnMsIFRhZ0FjdGlvbiwgQ2FtZXJhTW9kZSB9IGZyb20gJy4uL3R5cGVzLnNlcnZpY2UnO1xyXG5pbXBvcnQgeyBNYXR0ZXJwb3J0TmF2aWdhdGlvblNlcnZpY2UgfSBmcm9tICcuL21hdHRlcnBvcnQtbmF2aWdhdGlvbi5zZXJ2aWNlJztcclxuaW1wb3J0IHsgd2FpdCB9IGZyb20gJy4uL2hlbHBlcnMuc2VydmljZSc7XHJcbmltcG9ydCB7IEJhc2VUYWdTZXJ2aWNlIH0gZnJvbSAnLi90YWcuc2VydmljZSc7XHJcblxyXG5ASW5qZWN0YWJsZSh7XHJcbiAgcHJvdmlkZWRJbjogJ3Jvb3QnLFxyXG59KVxyXG5leHBvcnQgY2xhc3MgTWF0dGVycG9ydFRhZ1NlcnZpY2Uge1xyXG4gIHB1YmxpYyBkaWN0aW9ubmFyeVRhZ3M6IE1hcDxzdHJpbmcsIE1hdHRlcnRhZ0RhdGE+ID0gbmV3IE1hcCgpO1xyXG4gIHB1YmxpYyB0YWdBZGRRdWV1ZTogUHJvbWlzZTxhbnk+ID0gUHJvbWlzZS5yZXNvbHZlKCk7XHJcbiAgcHVibGljIG1hdHRlcnRhZ1RvRm9sbG93OiBzdHJpbmcgfCBudWxsID0gbnVsbDtcclxuICBwdWJsaWMgb25Hb1RvVGFnID0gbmV3IFN1YmplY3Q8c3RyaW5nPigpO1xyXG4gIHB1YmxpYyBtYXR0ZXJ0YWdJRHM6IEFycmF5PHN0cmluZz4gPSBbXTtcclxuICBwdWJsaWMgdGFnc0F0dGFjaG1lbnRzOiBPYmplY3QgPSB7fTtcclxuICBwdWJsaWMgdGFnTWVzc2VuZ2VyT246IGJvb2xlYW4gPSBmYWxzZTtcclxuICBwdWJsaWMgdGFnU2VydmljZTogQmFzZVRhZ1NlcnZpY2UgfCBudWxsID0gbnVsbDtcclxuICBwcml2YXRlIHRhZ3NDdXJyZW50T3BhY2l0eTogTWFwPHN0cmluZywgbnVtYmVyPiA9IG5ldyBNYXAoKTtcclxuICBwcml2YXRlIHRhZ3NDdXJyZW50RW5hYmxlZDogTWFwPHN0cmluZywgYm9vbGVhbj4gPSBuZXcgTWFwKCk7XHJcblxyXG4gIGNvbnN0cnVjdG9yKFxyXG4gICAgcHJpdmF0ZSBuYXZpZ2F0aW9uU2VydmljZTogTWF0dGVycG9ydE5hdmlnYXRpb25TZXJ2aWNlXHJcbiAgKSB7IH1cclxuXHJcbiAgc2V0VGFnU2VydmljZShzZXJ2aWNlOiBCYXNlVGFnU2VydmljZSk6IHZvaWQge1xyXG4gICAgdGhpcy50YWdTZXJ2aWNlID0gc2VydmljZTtcclxuICB9XHJcblxyXG4gIC8qKiBPcGVucyBhIHNwZWNpZmljIHRhZyBpbiB0aGUgTWF0dGVycG9ydCB2aWV3ZXIgYnkgaXRzIElELiAqL1xyXG4gIGFzeW5jIGdvVG9UYWcoc2RrOiBhbnksIHNpZDogc3RyaW5nKTogUHJvbWlzZTxhbnk+IHtcclxuICAgIGlmICghc2RrKSByZXR1cm47XHJcbiAgICB0cnkge1xyXG4gICAgICB0aGlzLm9uR29Ub1RhZy5uZXh0KHNpZCk7XHJcbiAgICAgIGF3YWl0IHNkay5UYWcub3BlbihzaWQpO1xyXG4gICAgfSBjYXRjaCAoZSkge1xyXG4gICAgICBpZiAoaXNEZXZNb2RlKCkpIGNvbnNvbGUud2FybignQ2Fubm90IG9wZW4gdGFnJywgc2lkLCBlKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIC8qKiBPcGVucyB0aGUgbW9zdCByZWNlbnRseSBjcmVhdGVkIHRhZyBpbiB0aGUgdmlld2VyLiAqL1xyXG4gIGFzeW5jIGdvVG9MYXN0VGFnKHNkazogYW55KTogUHJvbWlzZTxhbnk+IHtcclxuICAgIGlmICghc2RrIHx8IHRoaXMubWF0dGVydGFnSURzLmxlbmd0aCA9PT0gMCkgcmV0dXJuO1xyXG4gICAgY29uc3QgbGFzdFNpZCA9IHRoaXMubWF0dGVydGFnSURzW3RoaXMubWF0dGVydGFnSURzLmxlbmd0aCAtIDFdO1xyXG4gICAgcmV0dXJuIHRoaXMuZ29Ub1RhZyhzZGssIGxhc3RTaWQpO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogQWRkcyBhIE1hdHRlcnRhZyB0byB0aGUgdmlld2VyLCBzZXJpYWxpemluZyBjYWxscyB0byBwcmV2ZW50IFNESyByYWNlIGNvbmRpdGlvbnMuXHJcbiAgICogUmV1c2VzIGV4aXN0aW5nIElEcyBpZiB0aGUgdGFnIGlzIGFscmVhZHkgcHJlc2VudCBpbiB0aGUgc2Vzc2lvbi5cclxuICAgKi9cclxuICBhc3luYyBhZGRNYXR0ZXJ0YWdUb1ZpZXdlcihzZGs6IGFueSwgbWF0dGVydGFnRGF0YTogTWF0dGVydGFnRGF0YSk6IFByb21pc2U8c3RyaW5nIHwgbnVsbD4ge1xyXG4gICAgaWYgKCFzZGspIHJldHVybiBudWxsO1xyXG5cclxuICAgIHRoaXMudGFnQWRkUXVldWUgPSB0aGlzLnRhZ0FkZFF1ZXVlLnRoZW4oYXN5bmMgKCkgPT4ge1xyXG4gICAgICBjb25zdCBkYXRhID0gbWF0dGVydGFnRGF0YS5nZXREYXRhKCkgYXMgYW55O1xyXG4gICAgICBjb25zdCBleGlzdGluZ0lkID0gZGF0YT8uaWQgfHwgbnVsbDtcclxuXHJcbiAgICAgIHRyeSB7XHJcbiAgICAgICAgY29uc3Qgc2lkTGlzdCA9IGF3YWl0IHNkay5UYWcuYWRkKGRhdGEpO1xyXG4gICAgICAgIGlmIChzaWRMaXN0ICYmIHNpZExpc3QubGVuZ3RoID4gMCkge1xyXG4gICAgICAgICAgY29uc3QgbWF0dGVydGFnSUQgPSBzaWRMaXN0WzBdO1xyXG4gICAgICAgICAgdGhpcy5tYXR0ZXJ0YWdJRHMucHVzaChtYXR0ZXJ0YWdJRCk7XHJcbiAgICAgICAgICB0aGlzLmRpY3Rpb25uYXJ5VGFncy5zZXQobWF0dGVydGFnSUQsIG1hdHRlcnRhZ0RhdGEpO1xyXG4gICAgICAgICAgcmV0dXJuIG1hdHRlcnRhZ0lEO1xyXG4gICAgICAgIH1cclxuICAgICAgfSBjYXRjaCAoZXJyb3I6IGFueSkge1xyXG4gICAgICAgIGlmIChlcnJvcj8ubWVzc2FnZT8uaW5jbHVkZXMoJ2FscmVhZHkgaW4gdXNlJykgJiYgZXhpc3RpbmdJZCkge1xyXG4gICAgICAgICAgaWYgKCF0aGlzLmRpY3Rpb25uYXJ5VGFncy5oYXMoZXhpc3RpbmdJZCkpIHtcclxuICAgICAgICAgICAgdGhpcy5tYXR0ZXJ0YWdJRHMucHVzaChleGlzdGluZ0lkKTtcclxuICAgICAgICAgICAgdGhpcy5kaWN0aW9ubmFyeVRhZ3Muc2V0KGV4aXN0aW5nSWQsIG1hdHRlcnRhZ0RhdGEpO1xyXG4gICAgICAgICAgfVxyXG4gICAgICAgICAgcmV0dXJuIGV4aXN0aW5nSWQ7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGlmIChpc0Rldk1vZGUoKSkgY29uc29sZS53YXJuKCdGYWlsZWQgdG8gYWRkIHRhZyB0byB2aWV3ZXInLCBlcnJvcik7XHJcbiAgICAgIH1cclxuICAgICAgcmV0dXJuIG51bGw7XHJcbiAgICB9KTtcclxuXHJcbiAgICByZXR1cm4gdGhpcy50YWdBZGRRdWV1ZTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIEludGVybmFsIG1ldGhvZCB0byBhZGQgYW5kIGNvbmZpZ3VyZSBhIE1hdHRlcnRhZyB3aXRoIGljb24sIG9wYWNpdHksIGFuZCBIVE1MIGNvbnRlbnQuXHJcbiAgICogSGFuZGxlcyBleGlzdGluZyB0YWdzIGdyYWNlZnVsbHkgYW5kIHF1ZXVlcyBvcGVyYXRpb25zIHRvIGF2b2lkIFNESyBjb25mbGljdHMuXHJcbiAgICovXHJcbiAgYXN5bmMgX2RvQWRkTWF0dGVydGFnKFxyXG4gICAgc2RrOiBhbnksXHJcbiAgICBtYXR0ZXJ0YWdEYXRhOiBNYXR0ZXJ0YWdEYXRhLFxyXG4gICAgc2V0VGFnSWNvbkFuZE9wYWNpdHk6IChzaWQ6IHN0cmluZywgbXQ6IE1hdHRlcnRhZ0RhdGEpID0+IFByb21pc2U8dm9pZD4sXHJcbiAgICBpbmplY3RIdG1sSW5UYWc6ICh0eXBlOiBQb2lUeXBlLCBvYmo6IERiT2JqZWN0VHlwZSwgc2lkOiBzdHJpbmcpID0+IFByb21pc2U8dm9pZD5cclxuICApOiBQcm9taXNlPHN0cmluZz4ge1xyXG4gICAgY29uc3QgZGVzY3JpcHRvciA9IG1hdHRlcnRhZ0RhdGEuZ2V0TWF0dGVydGFnRGVzY3JpcHRvcigpO1xyXG4gICAgLy9jb25zb2xlLmxvZygnZGVzY3JpcHRvcicsIGRlc2NyaXB0b3IpO1xyXG4gICAgY29uc3Qgc2lkID0gZGVzY3JpcHRvclswXVsnaWQnXTtcclxuXHJcbiAgICBpZiAoc2lkICYmIHRoaXMuZGljdGlvbm5hcnlUYWdzLmhhcyhzaWQpKSB7XHJcbiAgICAgIGF3YWl0IHNldFRhZ0ljb25BbmRPcGFjaXR5KHNpZCwgbWF0dGVydGFnRGF0YSk7XHJcbiAgICAgIGF3YWl0IGluamVjdEh0bWxJblRhZyhtYXR0ZXJ0YWdEYXRhLmdldFR5cGUoKSwgbWF0dGVydGFnRGF0YS5nZXRPYmplY3QoKSwgc2lkKTtcclxuICAgICAgcmV0dXJuIHNpZDtcclxuICAgIH1cclxuXHJcbiAgICB0aGlzLnRhZ0FkZFF1ZXVlID0gdGhpcy50YWdBZGRRdWV1ZS50aGVuKGFzeW5jICgpID0+IHtcclxuICAgICAgdHJ5IHtcclxuICAgICAgICBjb25zdCBbY3JlYXRlZFNpZF0gPSBhd2FpdCBzZGsuVGFnLmFkZCguLi5kZXNjcmlwdG9yKTtcclxuICAgICAgICB0aGlzLm1hdHRlcnRhZ0lEcy5wdXNoKGNyZWF0ZWRTaWQpO1xyXG4gICAgICAgIHRoaXMuZGljdGlvbm5hcnlUYWdzLnNldChjcmVhdGVkU2lkLCBtYXR0ZXJ0YWdEYXRhKTtcclxuXHJcbiAgICAgICAgYXdhaXQgd2FpdCgxMDApO1xyXG4gICAgICAgIGF3YWl0IHNldFRhZ0ljb25BbmRPcGFjaXR5KGNyZWF0ZWRTaWQsIG1hdHRlcnRhZ0RhdGEpO1xyXG5cclxuICAgICAgICBpbmplY3RIdG1sSW5UYWcobWF0dGVydGFnRGF0YS5nZXRUeXBlKCksIG1hdHRlcnRhZ0RhdGEuZ2V0T2JqZWN0KCksIGNyZWF0ZWRTaWQpLmNhdGNoKGVyciA9PiB7XHJcbiAgICAgICAgICBpZiAoaXNEZXZNb2RlKCkpIGNvbnNvbGUud2FybignSFRNTCBpbmplY3Rpb24gZmFpbGVkIGZvcicsIGNyZWF0ZWRTaWQsIGVycik7XHJcbiAgICAgICAgfSk7XHJcblxyXG4gICAgICAgIHJldHVybiBjcmVhdGVkU2lkO1xyXG4gICAgICB9IGNhdGNoIChlOiBhbnkpIHtcclxuICAgICAgICBpZiAoZT8ubWVzc2FnZT8uaW5jbHVkZXMoJ2FscmVhZHkgaW4gdXNlJykgJiYgc2lkKSB7XHJcbiAgICAgICAgICBpZiAoIXRoaXMuZGljdGlvbm5hcnlUYWdzLmhhcyhzaWQpKSB7XHJcbiAgICAgICAgICAgIHRoaXMubWF0dGVydGFnSURzLnB1c2goc2lkKTtcclxuICAgICAgICAgICAgdGhpcy5kaWN0aW9ubmFyeVRhZ3Muc2V0KHNpZCwgbWF0dGVydGFnRGF0YSk7XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgICBhd2FpdCBzZXRUYWdJY29uQW5kT3BhY2l0eShzaWQsIG1hdHRlcnRhZ0RhdGEpO1xyXG4gICAgICAgICAgYXdhaXQgaW5qZWN0SHRtbEluVGFnKG1hdHRlcnRhZ0RhdGEuZ2V0VHlwZSgpLCBtYXR0ZXJ0YWdEYXRhLmdldE9iamVjdCgpLCBzaWQpO1xyXG4gICAgICAgICAgcmV0dXJuIHNpZDtcclxuICAgICAgICB9XHJcbiAgICAgICAgdGhyb3cgZTtcclxuICAgICAgfVxyXG4gICAgfSk7XHJcblxyXG4gICAgcmV0dXJuIHRoaXMudGFnQWRkUXVldWU7XHJcbiAgfVxyXG5cclxuICBnZXREaXN0YW5jZShwMTogYW55LCBwMjogYW55KTogbnVtYmVyIHtcclxuICAgIHJldHVybiBNYXRoLnNxcnQoTWF0aC5wb3cocDIueCAtIHAxLngsIDIpICsgTWF0aC5wb3cocDIueSAtIHAxLnksIDIpICsgTWF0aC5wb3cocDIueiAtIHAxLnosIDIpKTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIENoZWNrcyBpZiBhIHRhZyBpcyB3aXRoaW4gdGhlIGJvdW5kaW5nIGJveCBvZiBhbnkgYWN0aXZlIHJvb20gKGFkZGluZyBhIHNsaWdodCBtYXJnaW4gdG8gYWNjb3VudCBmb3Igd2FsbC1tb3VudGVkIHRhZ3MpLlxyXG4gICAqIElmIHRoZXJlIGFyZSBubyBhY3RpdmUgcm9vbXMgKGUuZy4sIGhhbGx3YXkpLCBmYWxscyBiYWNrIHRvIHJldHVybmluZyB0cnVlLlxyXG4gICAqL1xyXG4gIGlzVGFnSW5Sb29tcyhtYXR0ZXJ0YWdEYXRhOiBNYXR0ZXJ0YWdEYXRhLCByb29tczogYW55W10pOiBib29sZWFuIHtcclxuICAgIGlmICghcm9vbXMgfHwgcm9vbXMubGVuZ3RoID09PSAwKSByZXR1cm4gZmFsc2U7XHJcblxyXG4gICAgY29uc3QgdGFnUG9zID0gbWF0dGVydGFnRGF0YS5nZXRQb3NpdGlvbigpO1xyXG4gICAgY29uc3QgbWFyZ2luID0gMS41O1xyXG5cclxuICAgIHJldHVybiByb29tcy5zb21lKChyb29tKSA9PiB7XHJcbiAgICAgIGlmICghcm9vbS5ib3VuZHMpIHJldHVybiBmYWxzZTtcclxuICAgICAgY29uc3QgeyBtaW4sIG1heCB9ID0gcm9vbS5ib3VuZHM7XHJcblxyXG4gICAgICByZXR1cm4gKFxyXG4gICAgICAgIHRhZ1Bvcy54ID49IG1pbi54IC0gbWFyZ2luICYmIHRhZ1Bvcy54IDw9IG1heC54ICsgbWFyZ2luICYmXHJcbiAgICAgICAgdGFnUG9zLnkgPj0gbWluLnkgLSBtYXJnaW4gJiYgdGFnUG9zLnkgPD0gbWF4LnkgKyBtYXJnaW4gJiZcclxuICAgICAgICB0YWdQb3MueiA+PSBtaW4ueiAtIG1hcmdpbiAmJiB0YWdQb3MueiA8PSBtYXgueiArIG1hcmdpblxyXG4gICAgICApO1xyXG4gICAgfSk7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBDb21wdXRlcyB0aGUgZmluYWwgY29udGV4dC1hd2FyZSBvcGFjaXR5IGZvciBhIHNpbmdsZSB0YWcuXHJcbiAgICogQHBhcmFtIGN1cnJlbnRGbG9vclNlcXVlbmNlICBBdXRob3JpdGF0aXZlIGN1cnJlbnQgZmxvb3Igc2VxdWVuY2UgZnJvbSBzZGsuRmxvb3IuY3VycmVudFxyXG4gICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKG51bGwgPSBzaW5nbGUtZmxvb3IgbW9kZWwgb3IgdW5rbm93bikuXHJcbiAgICogQHBhcmFtIGN1cnJlbnRSb29tcyAgICAgICAgICBBcnJheSBvZiBhY3RpdmUgcm9vbXMgdGhlIGNhbWVyYSBpcyBpbi5cclxuICAgKi9cclxuICAvKmNvbXB1dGVTaW5nbGVUYWdDb250ZXh0T3BhY2l0eShcclxuICAgIG1hdHRlcnRhZ0RhdGE6IE1hdHRlcnRhZ0RhdGEsXHJcbiAgICBwb3NlQ2FtZXJhOiBhbnksXHJcbiAgICBzd2VlcENvbGxlY3Rpb246IGFueSxcclxuICAgIGN1cnJlbnRGbG9vclNlcXVlbmNlOiBudW1iZXIgfCBudWxsLFxyXG4gICAgY3VycmVudFJvb21zOiBhbnlbXVxyXG4gICk6IG51bWJlciB7XHJcbiAgICBjb25zdCBtb2RlID0gdGhpcy5uYXZpZ2F0aW9uU2VydmljZS5jdXJyZW50Q2FtZXJhTW9kZTtcclxuXHJcbiAgICAvLyAxLiBDaGVjayBGbG9vclxyXG4gICAgY29uc3QgdGFnRmxvb3JJZCA9IHRoaXMuZ2V0Rmxvb3JJZEZvclRhZyhtYXR0ZXJ0YWdEYXRhLCBzd2VlcENvbGxlY3Rpb24pO1xyXG4gICAgY29uc3QgY3VycmVudEZsb29ySWQgPSBjdXJyZW50Rmxvb3JTZXF1ZW5jZT8udG9TdHJpbmcoKTtcclxuICAgIGlmICh0YWdGbG9vcklkICYmIGN1cnJlbnRGbG9vcklkICYmIHRhZ0Zsb29ySWQgIT09IGN1cnJlbnRGbG9vcklkKSB7XHJcbiAgICAgIHJldHVybiAwO1xyXG4gICAgfVxyXG5cclxuICAgIC8vIDIuIFNpIERvbGxob3VzZSAtPiBQbGVpbmUgb3BhY2l0w6lcclxuICAgIC8vaWYgKG1vZGUgIT09IENhbWVyYU1vZGUuSU5TSURFKSByZXR1cm4gMTtcclxuXHJcbiAgICAvLyAzLiBTaSBJbnNpZGUgLT4gQ2hlY2sgcGnDqGNlICsgRGlzdGFuY2UgcHJvZ3Jlc3NpdmVcclxuICAgIC8vaWYgKCF0aGlzLmlzVGFnSW5Sb29tcyhtYXR0ZXJ0YWdEYXRhLCBjdXJyZW50Um9vbXMpKSByZXR1cm4gMDtcclxuXHJcbiAgICByZXR1cm4gMTtcclxuICB9Ki9cclxuXHJcbiAgLyoqIFJldHVybnMgdGhlIElEIG9mIHRoZSBtb3N0IHJlY2VudGx5IGFkZGVkIHRhZy4gKi9cclxuICBnZXRMYXN0VGFnKCk6IHN0cmluZyB8IG51bGwge1xyXG4gICAgaWYgKHRoaXMubWF0dGVydGFnSURzLmxlbmd0aCA9PT0gMCkgcmV0dXJuIG51bGw7XHJcbiAgICByZXR1cm4gdGhpcy5tYXR0ZXJ0YWdJRHNbdGhpcy5tYXR0ZXJ0YWdJRHMubGVuZ3RoIC0gMV07XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBVcGRhdGVzIHRoZSB2aXNpYmlsaXR5IChvcGFjaXR5KSBvZiBhbGwgdGFncyBiYXNlZCBvbiB0aGUgY3VycmVudCBjYW1lcmEgbW9kZSxcclxuICAgKiBmbG9vciBhbmQgcm9vbSBjb250ZXh0LiBNdXN0IGJlIGNhbGxlZCBhZnRlciBlYWNoIHN3ZWVwLCBmbG9vciBvciBtb2RlIGNoYW5nZS5cclxuICAgKlxyXG4gICAqIFJ1bGVzOlxyXG4gICAqICAtIERPTExIT1VTRSAvIEZMT09SUExBTiDihpIgYWxsIHRhZ3MgaGlkZGVuIChvcGFjaXR5IDApLlxyXG4gICAqICAtIElOU0lERSDihpIgb25seSB0YWdzIHdob3NlIHN3ZWVwIGJlbG9uZ3MgdG8gdGhlIGN1cnJlbnQgZmxvb3IgYXJlIHNob3duO1xyXG4gICAqICAgIHByb3hpbWl0eS1iYXNlZCBvcGFjaXR5IGlzIGFwcGxpZWQgdmlhIGNvbXB1dGVUYWdPcGFjaXR5KCkuXHJcbiAgICogICAgVGFncyBvbiBvdGhlciBmbG9vcnMgYXJlIGhpZGRlbiAob3BhY2l0eSAwKS5cclxuICAgKiAgLSBUUkFOU0lUSU9OSU5HIOKGkiBubyBjaGFuZ2UgKHNraXAgdXBkYXRlIHRvIGF2b2lkIGZsaWNrZXJpbmcpLlxyXG4gICAqXHJcbiAgICogQHBhcmFtIHNkayAgICAgICAgICBNYXR0ZXJwb3J0IFNESyBpbnN0YW5jZS5cclxuICAgKiBAcGFyYW0gcG9zZUNhbWVyYSAgIEN1cnJlbnQgY2FtZXJhIHBvc2UuXHJcbiAgICogQHBhcmFtIHN3ZWVwQ29sbGVjdGlvbiAgRnVsbCBjb2xsZWN0aW9uIG9mIHN3ZWVwcy5cclxuICAgKiBAcGFyYW0gY3VycmVudENhbWVyYU1vZGUgIEN1cnJlbnQgY2FtZXJhIG1vZGUuXHJcbiAgICogQHBhcmFtIG1hdHRlcnRhZ1RvRm9sbG93ICBJRCBvZiB0aGUgY3Vyc29yIHRhZyAobmV2ZXIgdG91Y2hlZCkuXHJcbiAgICovXHJcbiAgYXN5bmMgdXBkYXRlVGFnc1Zpc2liaWxpdHlGb3JDb250ZXh0KFxyXG4gICAgc2RrOiBhbnksXHJcbiAgICBzd2VlcENvbGxlY3Rpb246IGFueSxcclxuICAgIGN1cnJlbnRDYW1lcmFNb2RlOiBDYW1lcmFNb2RlLFxyXG4gICAgbWF0dGVydGFnVG9Gb2xsb3c6IHN0cmluZyB8IG51bGwsXHJcbiAgICBjdXJyZW50Rmxvb3JTZXF1ZW5jZTogbnVtYmVyIHwgbnVsbCA9IG51bGwsXHJcbiAgICBjdXJyZW50Um9vbXM6IGFueVtdID0gW11cclxuICApOiBQcm9taXNlPHZvaWQ+IHtcclxuICAgIGlmICghc2RrIHx8IHRoaXMuZGljdGlvbm5hcnlUYWdzLnNpemUgPT09IDApIHJldHVybjtcclxuXHJcbiAgICBjb25zdCBpc0ludGVyaW9yTW9kZSA9IGN1cnJlbnRDYW1lcmFNb2RlID09PSBDYW1lcmFNb2RlLklOU0lERTtcclxuICAgIGNvbnN0IGN1cnJlbnRGbG9vcklkID0gY3VycmVudEZsb29yU2VxdWVuY2UgIT09IG51bGwgPyBjdXJyZW50Rmxvb3JTZXF1ZW5jZS50b1N0cmluZygpIDogbnVsbDtcclxuICAgIGNvbnN0IHByb21pc2VzID0gW107XHJcblxyXG4gICAgZm9yIChjb25zdCBbdGFnSWQsIG1hdHRlcnRhZ0RhdGFdIG9mIHRoaXMuZGljdGlvbm5hcnlUYWdzKSB7XHJcbiAgICAgIGlmICh0YWdJZCA9PT0gbWF0dGVydGFnVG9Gb2xsb3cpIGNvbnRpbnVlO1xyXG5cclxuICAgICAgY29uc3QgdGFnRmxvb3JJZCA9IHRoaXMuZ2V0Rmxvb3JJZEZvclRhZyhtYXR0ZXJ0YWdEYXRhLCBzd2VlcENvbGxlY3Rpb24pO1xyXG4gICAgICBjb25zdCBpc09uQ3VycmVudEZsb29yID0gIXRhZ0Zsb29ySWQgfHwgIWN1cnJlbnRGbG9vcklkIHx8IHRhZ0Zsb29ySWQgPT09IGN1cnJlbnRGbG9vcklkO1xyXG5cclxuICAgICAgbGV0IHRhcmdldE9wYWNpdHkgPSAwO1xyXG4gICAgICBsZXQgc2hvdWxkQmVFbmFibGVkID0gZmFsc2U7XHJcblxyXG4gICAgICAvLyBDYWxjdWxhdGlvbiBvZiBvcGFjaXR5IGFuZCBlbmFibGUgc3RhdHVzXHJcbiAgICAgIGlmIChpc09uQ3VycmVudEZsb29yKSB7XHJcbiAgICAgICAgaWYgKCFpc0ludGVyaW9yTW9kZSkge1xyXG4gICAgICAgICAgdGFyZ2V0T3BhY2l0eSA9IDE7XHJcbiAgICAgICAgICBzaG91bGRCZUVuYWJsZWQgPSB0cnVlO1xyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICB0YXJnZXRPcGFjaXR5ID0gMC45O1xyXG4gICAgICAgICAgc2hvdWxkQmVFbmFibGVkID0gdHJ1ZTtcclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgICAgLy8gQXBwbHkgY2hhbmdlc1xyXG5cclxuICAgICAgLy8gVG9vbHRpcCBhbmQgY2xpY2sgbWFuYWdlbWVudFxyXG4gICAgICBjb25zdCBsYXN0RW5hYmxlZCA9IHRoaXMudGFnc0N1cnJlbnRFbmFibGVkLmdldCh0YWdJZCk7XHJcbiAgICAgIGlmIChsYXN0RW5hYmxlZCAhPT0gc2hvdWxkQmVFbmFibGVkKSB7XHJcbiAgICAgICAgdGhpcy50YWdzQ3VycmVudEVuYWJsZWQuc2V0KHRhZ0lkLCBzaG91bGRCZUVuYWJsZWQpO1xyXG4gICAgICAgIHByb21pc2VzLnB1c2goc2RrLlRhZy5hbGxvd0FjdGlvbih0YWdJZCwge1xyXG4gICAgICAgICAgb3BlbmluZzogc2hvdWxkQmVFbmFibGVkLFxyXG4gICAgICAgICAgbmF2aWdhdGluZzogc2hvdWxkQmVFbmFibGVkLFxyXG4gICAgICAgICAgZG9ja2luZzogZmFsc2VcclxuICAgICAgICB9KS5jYXRjaCgoKSA9PiB7IH0pKTtcclxuICAgICAgfVxyXG4gICAgICAvLyBPcGFjaXR5IG1hbmFnZW1lbnRcclxuICAgICAgY29uc3QgbGFzdE9wYWNpdHkgPSB0aGlzLnRhZ3NDdXJyZW50T3BhY2l0eS5nZXQodGFnSWQpID8/IC0xO1xyXG4gICAgICBpZiAoTWF0aC5hYnMobGFzdE9wYWNpdHkgLSB0YXJnZXRPcGFjaXR5KSA+IDAuMDUpIHtcclxuICAgICAgICB0aGlzLnRhZ3NDdXJyZW50T3BhY2l0eS5zZXQodGFnSWQsIHRhcmdldE9wYWNpdHkpO1xyXG4gICAgICAgIHByb21pc2VzLnB1c2goc2RrLlRhZy5lZGl0T3BhY2l0eSh0YWdJZCwgdGFyZ2V0T3BhY2l0eSkuY2F0Y2goKCkgPT4geyB9KSk7XHJcbiAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICBhd2FpdCBQcm9taXNlLmFsbChwcm9taXNlcyk7XHJcbiAgfVxyXG5cclxuICAvKiogUmVtb3ZlcyBhIHNwZWNpZmljIHRhZyBmcm9tIHRoZSB2aWV3ZXIgYW5kIGxvY2FsIGRpY3Rpb25hcmllcy4gKi9cclxuICBhc3luYyBkZWxldGVNYXR0ZXJ0YWdGcm9tSWQoc2RrOiBhbnksIG1hdHRlcnRhZ0lEOiBzdHJpbmcpOiBQcm9taXNlPHZvaWQ+IHtcclxuICAgIHRyeSB7XHJcbiAgICAgIGlmIChzZGspIGF3YWl0IHNkay5UYWcucmVtb3ZlKG1hdHRlcnRhZ0lEKTtcclxuICAgICAgdGhpcy5kaWN0aW9ubmFyeVRhZ3MuZGVsZXRlKG1hdHRlcnRhZ0lEKTtcclxuICAgICAgY29uc3QgaW5kZXggPSB0aGlzLm1hdHRlcnRhZ0lEcy5pbmRleE9mKG1hdHRlcnRhZ0lEKTtcclxuICAgICAgaWYgKGluZGV4ID4gLTEpIHRoaXMubWF0dGVydGFnSURzLnNwbGljZShpbmRleCwgMSk7XHJcbiAgICB9IGNhdGNoIChlOiBhbnkpIHtcclxuICAgICAgaWYgKGlzRGV2TW9kZSgpKSBjb25zb2xlLndhcm4oJ0Nhbm5vdCBkZWxldGUgdGFnJywgbWF0dGVydGFnSUQsIGUpO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLyoqIFJlbW92ZXMgdGhlIGxhc3QgYWRkZWQgdGFnIGZyb20gdGhlIHZpZXdlci4gKi9cclxuICBhc3luYyBkZWxldGVMYXN0TWF0dGVydGFnKHNkazogYW55KTogUHJvbWlzZTx2b2lkPiB7XHJcbiAgICBjb25zdCBsYXN0U2lkID0gdGhpcy5nZXRMYXN0VGFnKCk7XHJcbiAgICBpZiAobGFzdFNpZCkgYXdhaXQgdGhpcy5kZWxldGVNYXR0ZXJ0YWdGcm9tSWQoc2RrLCBsYXN0U2lkKTtcclxuICB9XHJcblxyXG4gIC8qKiBDbGVhcnMgYWxsIHRhZ3MgZnJvbSB0aGUgdmlld2VyIGFuZCByZXNldHMgbG9jYWwgc3RhdGUuICovXHJcbiAgYXN5bmMgYWN0aW9uX2RlbGV0ZV9hbGxfbWF0dGVydGFncyhzZGs6IGFueSk6IFByb21pc2U8dm9pZD4ge1xyXG4gICAgaWYgKHNkaykge1xyXG4gICAgICBjb25zdCBzaWRzVG9SZW1vdmUgPSBbLi4udGhpcy5tYXR0ZXJ0YWdJRHNdO1xyXG4gICAgICBmb3IgKGNvbnN0IHNpZCBvZiBzaWRzVG9SZW1vdmUpIHtcclxuICAgICAgICB0cnkge1xyXG4gICAgICAgICAgYXdhaXQgc2RrLlRhZy5yZW1vdmUoc2lkKTtcclxuICAgICAgICB9IGNhdGNoIChlKSB7IH1cclxuICAgICAgfVxyXG4gICAgfVxyXG4gICAgdGhpcy5jbGVhcigpO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogQ3JlYXRlcyBhbmQgY29uZmlndXJlcyBhIE1hdHRlcnRhZyBmcm9tIGEgUE9JLCBoYW5kbGluZyBjb29yZGluYXRlcywgbm9ybWFscywgYW5kIHN3ZWVwIElELlxyXG4gICAqIFNraXBzIGNyZWF0aW9uIGlmIGEgdGFnIGZvciB0aGUgb2JqZWN0IGFscmVhZHkgZXhpc3RzLlxyXG4gICAqL1xyXG4gIGFzeW5jIGNyZWF0ZU1hdHRlcnRhZ0Zyb21QT0koXHJcbiAgICBzZGs6IGFueSxcclxuICAgIHRhZ1R5cGU6IFBvaVR5cGUsXHJcbiAgICBvYmplY3Q6IERiT2JqZWN0VHlwZSxcclxuICAgIHBvaTogUE9JLFxyXG4gICAgcG9zZUNhbWVyYTogYW55LFxyXG4gICAgZ2V0VGFnRnJvbUVsZW1lbnRJZDogKGlkOiBzdHJpbmcpID0+IHsgdGFnOiBzdHJpbmc7IHN3ZWVwOiBzdHJpbmcgfSxcclxuICAgIHNldFRhZ0ljb25BbmRPcGFjaXR5OiAoc2lkOiBzdHJpbmcsIG10OiBNYXR0ZXJ0YWdEYXRhKSA9PiBQcm9taXNlPHZvaWQ+LFxyXG4gICAgaW5qZWN0SHRtbEluVGFnOiAodHlwZTogUG9pVHlwZSwgb2JqOiBEYk9iamVjdFR5cGUsIHNpZDogc3RyaW5nKSA9PiBQcm9taXNlPHZvaWQ+XHJcbiAgKTogUHJvbWlzZTxhbnk+IHtcclxuICAgIGNvbnN0IHsgdGFnIH0gPSBnZXRUYWdGcm9tRWxlbWVudElkKG9iamVjdC5pZCk7XHJcbiAgICBpZiAodGFnKSByZXR1cm47XHJcblxyXG4gICAgY29uc3QgbWF0dGVydGFnRGF0YTogTWF0dGVydGFnRGF0YSA9IG5ldyBNYXR0ZXJ0YWdEYXRhKHRhZ1R5cGUpO1xyXG4gICAgbWF0dGVydGFnRGF0YS5zZXRPYmplY3Qob2JqZWN0LCB0YWdUeXBlKTtcclxuXHJcbiAgICBpZiAocG9pLmNvb3JkaW5hdGUpIHtcclxuICAgICAgdHJ5IHtcclxuICAgICAgICBtYXR0ZXJ0YWdEYXRhLnNldFBvc2l0aW9uKEpTT04ucGFyc2UocG9pLmNvb3JkaW5hdGUpKTtcclxuICAgICAgfSBjYXRjaCAoZSkge1xyXG4gICAgICAgIGlmIChpc0Rldk1vZGUoKSkgY29uc29sZS53YXJuKCdFcnJvciBwYXJzaW5nIFBPSSBjb29yZGluYXRlcycsIHBvaS5jb29yZGluYXRlKTtcclxuICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIGlmIChwb2kubWV0YWRhdGEpIHtcclxuICAgICAgdHJ5IHtcclxuICAgICAgICBjb25zdCB0YWdNZXRhZGF0YSA9IEpTT04ucGFyc2UocG9pLm1ldGFkYXRhKTtcclxuICAgICAgICBtYXR0ZXJ0YWdEYXRhLnNldE5vcm1hbCh0YWdNZXRhZGF0YS5ub3JtYWwgfHwgeyB4OiAwLCB5OiAtMC4xNSwgejogMCB9KTtcclxuICAgICAgfSBjYXRjaCAoZSkge1xyXG4gICAgICAgIG1hdHRlcnRhZ0RhdGEuc2V0Tm9ybWFsKHsgeDogMCwgeTogLTAuMTUsIHo6IDAgfSk7XHJcbiAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICBpZiAocG9pLm1hdHRlcnBvcnRTd2VlcElEKSB7XHJcbiAgICAgIG1hdHRlcnRhZ0RhdGEuc2V0U3dlZXBJRChwb2kubWF0dGVycG9ydFN3ZWVwSUQpO1xyXG4gICAgfVxyXG4gICAgbWF0dGVydGFnRGF0YS5zZXRQb2kocG9pKTtcclxuXHJcbiAgICBjb25zdCBjcmVhdGVkVGFnSUQgPSBhd2FpdCB0aGlzLmFkZE1hdHRlcnRhZ1RvVmlld2VyKHNkaywgbWF0dGVydGFnRGF0YSk7XHJcblxyXG4gICAgaWYgKGNyZWF0ZWRUYWdJRCAmJiBzZGspIHtcclxuICAgICAgYXdhaXQgd2FpdCgxMDApO1xyXG4gICAgICBhd2FpdCBzZXRUYWdJY29uQW5kT3BhY2l0eShjcmVhdGVkVGFnSUQsIG1hdHRlcnRhZ0RhdGEpO1xyXG4gICAgICBpbmplY3RIdG1sSW5UYWcodGFnVHlwZSwgb2JqZWN0LCBjcmVhdGVkVGFnSUQpLmNhdGNoKGVyciA9PiB7XHJcbiAgICAgICAgaWYgKGlzRGV2TW9kZSgpKSBjb25zb2xlLndhcm4oJ0hUTUwgaW5qZWN0aW9uIGZhaWxlZCBmb3InLCBjcmVhdGVkVGFnSUQsIGVycik7XHJcbiAgICAgIH0pO1xyXG4gICAgfVxyXG5cclxuICAgIHJldHVybiBjcmVhdGVkVGFnSUQ7XHJcbiAgfVxyXG5cclxuICAvKiogVXBkYXRlcyB0aGUgaWNvbiwgb3BhY2l0eSwgYW5kIEhUTUwgY29udGVudCBvZiBhbiBleGlzdGluZyB0YWcuICovXHJcbiAgYXN5bmMgdXBkYXRlTWF0dGVyVGFnQ29udGVudEZvclRhZ0lEKFxyXG4gICAgc2RrOiBhbnksXHJcbiAgICBtYXR0ZXJ0YWdJRDogc3RyaW5nLFxyXG4gICAgb2JqZWN0OiBEYk9iamVjdFR5cGUsXHJcbiAgICBwb2lUeXBlOiBQb2lUeXBlLFxyXG4gICAgc2V0VGFnSWNvbkFuZE9wYWNpdHk6IChzaWQ6IHN0cmluZywgbXQ6IE1hdHRlcnRhZ0RhdGEpID0+IFByb21pc2U8dm9pZD4sXHJcbiAgICBpbmplY3RIdG1sSW5UYWc6ICh0eXBlOiBQb2lUeXBlLCBvYmo6IERiT2JqZWN0VHlwZSwgc2lkOiBzdHJpbmcpID0+IFByb21pc2U8dm9pZD5cclxuICApOiBQcm9taXNlPGFueT4ge1xyXG4gICAgY29uc3QgbWF0dGVydGFnRGF0YSA9IHRoaXMuZGljdGlvbm5hcnlUYWdzLmdldChtYXR0ZXJ0YWdJRCk7XHJcbiAgICBpZiAoIW1hdHRlcnRhZ0RhdGEpIHJldHVybjtcclxuXHJcbiAgICBpZiAob2JqZWN0KSB7XHJcbiAgICAgIG1hdHRlcnRhZ0RhdGEuc2V0T2JqZWN0KG9iamVjdCwgcG9pVHlwZSk7XHJcbiAgICB9XHJcblxyXG4gICAgYXdhaXQgc2V0VGFnSWNvbkFuZE9wYWNpdHkobWF0dGVydGFnSUQsIG1hdHRlcnRhZ0RhdGEpO1xyXG4gICAgYXdhaXQgaW5qZWN0SHRtbEluVGFnKHBvaVR5cGUsIG9iamVjdCwgbWF0dGVydGFnSUQpO1xyXG4gIH1cclxuXHJcbiAgLyoqIFJlZ2lzdGVycyBhIGN1c3RvbSB0ZXh0dXJlIGFuZCBhcHBsaWVzIGl0IHRvIGEgdGFnLCBvcHRpb25hbGx5IGFkanVzdGluZyBvcGFjaXR5LiAqL1xyXG4gIGFzeW5jIGFkZE5ld0ljb25BbmRTZXRGb3JUYWcoXHJcbiAgICBzZGs6IGFueSxcclxuICAgIG1hdHRlcnRhZ0lEOiBzdHJpbmcsXHJcbiAgICBpY29uUGF0aDogc3RyaW5nLFxyXG4gICAgYXBwbHlPcGFjaXR5OiBib29sZWFuLFxyXG4gICAgb3BhY2l0eTogbnVtYmVyXHJcbiAgKSB7XHJcbiAgICBpZiAoIXNkaykgcmV0dXJuO1xyXG4gICAgdHJ5IHtcclxuICAgICAgY29uc3QgaWNvbk5hbWUgPSBgY3VzdG9tLWljb24tJHttYXR0ZXJ0YWdJRH1gO1xyXG4gICAgICBhd2FpdCBzZGsuQXNzZXQucmVnaXN0ZXJUZXh0dXJlKGljb25OYW1lLCBpY29uUGF0aCk7XHJcbiAgICAgIGF3YWl0IHNkay5UYWcuZWRpdEljb24obWF0dGVydGFnSUQsIGljb25OYW1lKTtcclxuXHJcbiAgICAgIGlmIChhcHBseU9wYWNpdHkpIHtcclxuICAgICAgICBhd2FpdCBzZGsuVGFnLmVkaXRPcGFjaXR5KG1hdHRlcnRhZ0lELCBvcGFjaXR5KTtcclxuICAgICAgfVxyXG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcclxuICAgICAgaWYgKGlzRGV2TW9kZSgpKSBjb25zb2xlLndhcm4oJ0Vycm9yIHNldHRpbmcgY3VzdG9tIGljb24gb3Igb3BhY2l0eScsIGVycm9yKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIC8qKiBGaW5kcyB0aGUgdGFnIElEIGFuZCBzd2VlcCBJRCBhc3NvY2lhdGVkIHdpdGggYSBzcGVjaWZpYyBlbGVtZW50IElELiAqL1xyXG4gIGdldFRhZ0Zyb21FbGVtZW50SWQoZWxlbWVudElEOiBzdHJpbmcsIHN3ZWVwczogc3RyaW5nW10gfCBudWxsKTogeyB0YWc6IHN0cmluZyB8IG51bGw7IHN3ZWVwOiBzdHJpbmcgfCBudWxsIH0ge1xyXG4gICAgbGV0IHRhZ0lEID0gbnVsbDtcclxuICAgIGxldCBzd2VlcElEID0gbnVsbDtcclxuICAgIGZvciAobGV0IFttYXR0ZXJ0YWdJRCwgbWF0dGVydGFnRGF0YV0gb2YgdGhpcy5kaWN0aW9ubmFyeVRhZ3MpIHtcclxuICAgICAgaWYgKG1hdHRlcnRhZ0RhdGEuZWxlbWVudElEID09PSBlbGVtZW50SUQpIHtcclxuICAgICAgICB0YWdJRCA9IG1hdHRlcnRhZ0lEO1xyXG4gICAgICAgIGNvbnN0IHN3ZWVwID0gbWF0dGVydGFnRGF0YS5nZXRTd2VlcElEKCk7XHJcbiAgICAgICAgaWYgKHN3ZWVwICYmIHN3ZWVwcyAmJiBzd2VlcHMuaW5jbHVkZXMoc3dlZXApKSB7XHJcbiAgICAgICAgICBzd2VlcElEID0gc3dlZXA7XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgICByZXR1cm4geyB0YWc6IHRhZ0lELCBzd2VlcDogc3dlZXBJRCB9O1xyXG4gIH1cclxuXHJcbiAgLyoqIFJldHJpZXZlcyB0aGUgZmxvb3IgaWRlbnRpZmllciBhc3NvY2lhdGVkIHdpdGggYSB0YWcgYmFzZWQgb24gaXRzIHN3ZWVwIGRhdGEuXHJcbiAgICogIEhhbmRsZXMgYm90aCB0aGUgb2JqZWN0IGZvcm0gKHsgZmxvb3JJbmZvOiB7IGlkLCBzZXF1ZW5jZSB9LCBmbG9vcjogeyBpZCB9IH0pXHJcbiAgICogIGFuZCB0aGUgcHJpbWl0aXZlIGZvcm0gKGZsb29yOiBudW1iZXIpIHVzZWQgYnkgTWF0dGVycG9ydCBTREsgdjMuXHJcbiAgICovXHJcbiAgZ2V0Rmxvb3JJZEZvclRhZyhtYXR0ZXJ0YWdEYXRhOiBNYXR0ZXJ0YWdEYXRhLCBzd2VlcENvbGxlY3Rpb246IGFueSk6IHN0cmluZyB8IG51bGwge1xyXG4gICAgY29uc3Qgc3dlZXBJZCA9IG1hdHRlcnRhZ0RhdGEuZ2V0U3dlZXBJRCgpO1xyXG4gICAgaWYgKCFzd2VlcElkIHx8ICFzd2VlcENvbGxlY3Rpb24pIHJldHVybiBudWxsO1xyXG5cclxuICAgIGNvbnN0IHN3ZWVwRGF0YSA9IHN3ZWVwQ29sbGVjdGlvbltzd2VlcElkXTtcclxuICAgIGlmICghc3dlZXBEYXRhKSByZXR1cm4gbnVsbDtcclxuXHJcbiAgICAvLyBTREsgdjM6IHN3ZWVwLmZsb29yIGlzIGEgcHJpbWl0aXZlIG51bWJlciAodGhlIHNlcXVlbmNlIGluZGV4KVxyXG4gICAgaWYgKHR5cGVvZiBzd2VlcERhdGEuZmxvb3IgPT09ICdudW1iZXInKSB7XHJcbiAgICAgIHJldHVybiBzd2VlcERhdGEuZmxvb3IudG9TdHJpbmcoKTtcclxuICAgIH1cclxuXHJcbiAgICAvLyBPbGRlciAvIGV4dGVuZGVkIGZvcm1hdHNcclxuICAgIHJldHVybiBzd2VlcERhdGE/LmZsb29ySW5mbz8uaWRcclxuICAgICAgPz8gc3dlZXBEYXRhPy5mbG9vckluZm8/LnNlcXVlbmNlPy50b1N0cmluZygpXHJcbiAgICAgID8/IHN3ZWVwRGF0YT8uZmxvb3JJZFxyXG4gICAgICA/PyBzd2VlcERhdGE/LmZsb29yPy5pZFxyXG4gICAgICA/PyBzd2VlcERhdGE/LmZsb29yPy5zZXF1ZW5jZT8udG9TdHJpbmcoKVxyXG4gICAgICA/PyBudWxsO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogSW5qZWN0cyBjdXN0b20gSFRNTCBvciBmYWxsYmFjayBiaWxsYm9hcmQgbWVkaWEgaW50byBhIE1hdHRlcnRhZyBzYW5kYm94LlxyXG4gICAqIEF0dGFjaGVzIGV2ZW50IGxpc3RlbmVycyBmb3IgaW50ZXJhY3RpdmUgZWxlbWVudHMgd2l0aGluIHRoZSB0YWcuXHJcbiAgICovXHJcbiAgYXN5bmMgaW5qZWN0SHRtbEluVGFnKHNkazogYW55LCB0YWdUeXBlOiBQb2lUeXBlLCBvYmplY3Q6IERiT2JqZWN0VHlwZSwgdGFnSUQ6IHN0cmluZykge1xyXG4gICAgaWYgKCF0aGlzLnRhZ1NlcnZpY2UpIHtcclxuICAgICAgY29uc29sZS5lcnJvcignW01hdHRlcnBvcnRUYWdTZXJ2aWNlXSB0YWdTZXJ2aWNlIGlzIG5vdCBpbml0aWFsaXplZC4nKTtcclxuICAgICAgcmV0dXJuO1xyXG4gICAgfVxyXG4gICAgdHJ5IHtcclxuICAgICAgbGV0IGh0bWwgPSBhd2FpdCB0aGlzLnRhZ1NlcnZpY2UuZ2V0SHRtbFRvSW5qZWN0KHRhZ1R5cGUsIG9iamVjdCk7XHJcblxyXG4gICAgICBpZiAoaHRtbCAmJiBodG1sLnRyaW0oKS5sZW5ndGggPiAwICYmIHNkaykge1xyXG4gICAgICAgIGNvbnN0IHNjcmlwdFRhZyA9IHRoaXMudGFnU2VydmljZS5nZXRTY3JpcHRGb3JUYWcob2JqZWN0LCB0YWdUeXBlKTtcclxuICAgICAgICBodG1sICs9IGAke3NjcmlwdFRhZ31gO1xyXG5cclxuICAgICAgICBjb25zdCBbc2FuZGJveElkLCBtZXNzZW5nZXJdID0gYXdhaXQgc2RrLlRhZy5yZWdpc3RlclNhbmRib3goaHRtbCk7XHJcblxyXG4gICAgICAgIGNvbnN0IGF0dGFjaG1lbnRJRCA9IHRoaXMudGFnc0F0dGFjaG1lbnRzW3RhZ0lEXTtcclxuICAgICAgICBpZiAoYXR0YWNobWVudElEKSB7XHJcbiAgICAgICAgICB0cnkge1xyXG4gICAgICAgICAgICBhd2FpdCBzZGsuVGFnLmRldGFjaCh0YWdJRCwgYXR0YWNobWVudElEKTtcclxuICAgICAgICAgIH0gY2F0Y2ggKGUpIHsgfVxyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgdGhpcy50YWdzQXR0YWNobWVudHNbdGFnSURdID0gc2FuZGJveElkO1xyXG4gICAgICAgIGF3YWl0IHNkay5UYWcuYXR0YWNoKHRhZ0lELCBzYW5kYm94SWQpO1xyXG5cclxuICAgICAgICAvLyBBdHRhY2ggdGhlIFwiVmlldyBpbmZvcm1hdGlvbnNcIiBoYW5kbGVyIGluIHRvb2x0aXBcclxuICAgICAgICBtZXNzZW5nZXIub24oVGFnQWN0aW9uLkRFVEFJTF9DTElDSywgdGhpcy50YWdTZXJ2aWNlLm9uQWN0aW9uRGV0YWlsQ2xpY2suYmluZCh0aGlzLnRhZ1NlcnZpY2UpKTtcclxuICAgICAgICBtZXNzZW5nZXIub24oVGFnQWN0aW9uLlRJQ0tFVF9DTElDSywgdGhpcy50YWdTZXJ2aWNlLm9uQWN0aW9uRGV0YWlsQ2xpY2suYmluZCh0aGlzLnRhZ1NlcnZpY2UpKTtcclxuICAgICAgICBtZXNzZW5nZXIub24oVGFnQWN0aW9uLkFVRElPX0NMSUNLLCAoYXVkaW9Db21tZW50SUQ6IHN0cmluZykgPT4gdGhpcy50YWdTZXJ2aWNlLm9uQWN0aW9uQXVkaW9DbGljayhhdWRpb0NvbW1lbnRJRCkpO1xyXG4gICAgICAgIG1lc3Nlbmdlci5vbihUYWdBY3Rpb24uVklERU9fQ0xJQ0ssICh2aWRlb1VybDogc3RyaW5nKSA9PiB0aGlzLnRhZ1NlcnZpY2Uub25BY3Rpb25WaWRlb0NsaWNrKHZpZGVvVXJsKSk7XHJcbiAgICAgICAgbWVzc2VuZ2VyLm9uKFRhZ0FjdGlvbi5JTUFHRV9DTElDSywgKGltYWdlQ29tbWVudElEOiBzdHJpbmcpID0+IHRoaXMudGFnU2VydmljZS5vbkFjdGlvbkltYWdlQ2xpY2soaW1hZ2VDb21tZW50SUQpKTtcclxuICAgICAgICBtZXNzZW5nZXIub24oVGFnQWN0aW9uLkRPQ19DTElDSywgKGRvY1VybDogc3RyaW5nKSA9PiB0aGlzLnRhZ1NlcnZpY2Uub25BY3Rpb25Eb2NDbGljayhkb2NVcmwpKTtcclxuICAgICAgICBtZXNzZW5nZXIub24oVGFnQWN0aW9uLllPVVRVQkVfQ0xJQ0ssICh5b3V0dWJlVXJsOiBzdHJpbmcpID0+IHRoaXMudGFnU2VydmljZS5vbkFjdGlvbllvdXR1YmVDbGljayh5b3V0dWJlVXJsKSk7XHJcbiAgICAgIH0gZWxzZSBpZiAoc2RrKSB7XHJcbiAgICAgICAgY29uc3QgeyBjb21tZW50LCB0YWdEZXNjcmlwdGlvbiB9ID0gdGhpcy50YWdTZXJ2aWNlLmdldEJpbGxib2FyZE1lZGlhVG9FbWJlZChvYmplY3QpO1xyXG5cclxuICAgICAgICBpZiAoY29tbWVudCkge1xyXG4gICAgICAgICAgY29uc3QgYXR0YWNobWVudElEID0gYXdhaXQgc2RrLlRhZy5yZWdpc3RlckF0dGFjaG1lbnQoe1xyXG4gICAgICAgICAgICB0eXBlOiAnbWVkaWEnLFxyXG4gICAgICAgICAgICBkYXRhOiB7XHJcbiAgICAgICAgICAgICAgdXJsOiBjb21tZW50LmV4dGVybmFsTGluayxcclxuICAgICAgICAgICAgICBsYWJlbDogb2JqZWN0LnRpdGxlIHx8ICdNZWRpYScsXHJcbiAgICAgICAgICAgIH0sXHJcbiAgICAgICAgICB9KTtcclxuXHJcbiAgICAgICAgICBhd2FpdCBzZGsuVGFnLmF0dGFjaCh0YWdJRCwgYXR0YWNobWVudElEKTtcclxuXHJcbiAgICAgICAgICBjb25zdCBiaWxsYm9hcmRBdHRhY2htZW50SUQgPSBhd2FpdCBzZGsuVGFnLnJlZ2lzdGVyQXR0YWNobWVudCh7XHJcbiAgICAgICAgICAgIHR5cGU6ICdiaWxsYm9hcmQnLFxyXG4gICAgICAgICAgICBkYXRhOiB7XHJcbiAgICAgICAgICAgICAgdGl0bGU6IG9iamVjdC50aXRsZSxcclxuICAgICAgICAgICAgICBkZXNjcmlwdGlvbjogdGFnRGVzY3JpcHRpb24sXHJcbiAgICAgICAgICAgIH0sXHJcbiAgICAgICAgICB9KTtcclxuXHJcbiAgICAgICAgICBhd2FpdCBzZGsuVGFnLmF0dGFjaCh0YWdJRCwgYmlsbGJvYXJkQXR0YWNobWVudElEKTtcclxuICAgICAgICAgIHRoaXMudGFnc0F0dGFjaG1lbnRzW3RhZ0lEXSA9IGJpbGxib2FyZEF0dGFjaG1lbnRJRDtcclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgIH0gY2F0Y2ggKGVycm9yKSB7XHJcbiAgICAgIGNvbnNvbGUuZXJyb3IoJ1tNYXR0ZXJwb3J0VGFnU2VydmljZV0gRXJyb3IgaW4gaW5qZWN0SHRtbEluVGFnOicsIGVycm9yKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIC8qKiBDbGVhcnMgYWxsIGxvY2FsIHRhZyBkYXRhIGFuZCByZXNldHMgdGhlIGFkZGl0aW9uIHF1ZXVlLiAqL1xyXG4gIGNsZWFyKCkge1xyXG4gICAgdGhpcy5kaWN0aW9ubmFyeVRhZ3MuY2xlYXIoKTtcclxuICAgIHRoaXMudGFnQWRkUXVldWUgPSBQcm9taXNlLnJlc29sdmUoKTtcclxuICAgIHRoaXMubWF0dGVydGFnVG9Gb2xsb3cgPSBudWxsO1xyXG4gICAgdGhpcy5tYXR0ZXJ0YWdJRHMgPSBbXTtcclxuICB9XHJcbn1cclxuIl19
|