@ks89/angular-modal-gallery 8.0.0-beta.5 → 9.0.0
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/CHANGELOG.md +153 -0
- package/CONTRIBUTING.md +20 -38
- package/LICENSE +1 -1
- package/README.md +36 -42
- package/esm2020/ks89-angular-modal-gallery.mjs +5 -0
- package/esm2020/lib/components/accessibility-default.mjs +41 -0
- package/esm2020/lib/components/accessible.component.mjs +130 -0
- package/esm2020/lib/components/carousel/carousel-previews/carousel-previews.component.mjs +462 -0
- package/esm2020/lib/components/carousel/carousel.component.mjs +747 -0
- package/esm2020/lib/components/components.mjs +50 -0
- package/esm2020/lib/components/current-image/current-image.component.mjs +616 -0
- package/esm2020/lib/components/current-image/loading-spinner/loading-spinner.component.mjs +80 -0
- package/esm2020/lib/components/dots/dots.component.mjs +127 -0
- package/esm2020/lib/components/modal-gallery/modal-gallery-ref.mjs +103 -0
- package/esm2020/lib/components/modal-gallery/modal-gallery.component.mjs +523 -0
- package/esm2020/lib/components/modal-gallery/modal-gallery.service.mjs +187 -0
- package/esm2020/lib/components/modal-gallery/modal-gallery.tokens.mjs +26 -0
- package/esm2020/lib/components/plain-gallery/plain-gallery.component.mjs +249 -0
- package/esm2020/lib/components/previews/previews.component.mjs +332 -0
- package/esm2020/lib/components/upper-buttons/upper-buttons-default.mjs +76 -0
- package/esm2020/lib/components/upper-buttons/upper-buttons.component.mjs +249 -0
- package/esm2020/lib/directives/a-tag-bg-image.directive.mjs +78 -0
- package/esm2020/lib/directives/click-outside.directive.mjs +91 -0
- package/esm2020/lib/directives/description.directive.mjs +98 -0
- package/esm2020/lib/directives/direction.directive.mjs +73 -0
- package/esm2020/lib/directives/directives.mjs +49 -0
- package/esm2020/lib/directives/fallback-image.directive.mjs +59 -0
- package/esm2020/lib/directives/keyboard-navigation.directive.mjs +58 -0
- package/esm2020/lib/directives/margin.directive.mjs +84 -0
- package/esm2020/lib/directives/max-size.directive.mjs +75 -0
- package/esm2020/lib/directives/size.directive.mjs +76 -0
- package/{esm2015/lib/directives/size.directive.js → esm2020/lib/directives/wrap.directive.mjs} +23 -22
- package/esm2020/lib/modal-gallery.module.mjs +94 -0
- package/esm2020/lib/model/accessibility.interface.mjs +25 -0
- package/esm2020/lib/model/action.enum.mjs +36 -0
- package/esm2020/lib/model/buttons-config.interface.mjs +62 -0
- package/esm2020/lib/model/carousel-config.interface.mjs +25 -0
- package/esm2020/lib/model/carousel-image-config.interface.mjs +25 -0
- package/esm2020/lib/model/carousel-preview-config.interface.mjs +25 -0
- package/{esm2015/lib/model/keyboard-service-config.interface.js → esm2020/lib/model/current-image-config.interface.mjs} +2 -2
- package/esm2020/lib/model/description.interface.mjs +33 -0
- package/{esm2015/lib/model/preview-config.interface.js → esm2020/lib/model/dots-config.interface.mjs} +2 -2
- package/esm2020/lib/model/image-internal.class.mjs +35 -0
- package/esm2020/lib/model/image.class.mjs +54 -0
- package/esm2020/lib/model/interaction-event.interface.mjs +2 -0
- package/esm2020/lib/model/keyboard-config.interface.mjs +25 -0
- package/esm2020/lib/model/keyboard-service-config.interface.mjs +25 -0
- package/esm2020/lib/model/keyboard.enum.mjs +35 -0
- package/esm2020/lib/model/lib-config.interface.mjs +25 -0
- package/esm2020/lib/model/loading-config.interface.mjs +37 -0
- package/{esm2015/lib/model/dots-config.interface.js → esm2020/lib/model/max-size.interface.mjs} +2 -2
- package/{esm2015/lib/model/carousel-preview-config.interface.js → esm2020/lib/model/modal-gallery-config.interface.mjs} +2 -2
- package/esm2020/lib/model/plain-gallery-config.interface.mjs +55 -0
- package/{esm2015/lib/model/image-internal.class.js → esm2020/lib/model/play-config.interface.mjs} +3 -13
- package/esm2020/lib/model/preview-config.interface.mjs +25 -0
- package/esm2020/lib/model/size.interface.mjs +25 -0
- package/{esm2015/lib/model/carousel-config.interface.js → esm2020/lib/model/slide-config.interface.mjs} +2 -2
- package/esm2020/lib/services/config.service.mjs +396 -0
- package/esm2020/lib/services/id-validator.service.mjs +71 -0
- package/esm2020/lib/services/keyboard.service.mjs +111 -0
- package/esm2020/lib/utils/image.util.mjs +48 -0
- package/esm2020/lib/utils/user-input.util.mjs +104 -0
- package/esm2020/public-api.mjs +42 -0
- package/fesm2015/ks89-angular-modal-gallery.mjs +5782 -0
- package/fesm2015/ks89-angular-modal-gallery.mjs.map +1 -0
- package/{fesm2015/ks89-angular-modal-gallery.js → fesm2020/ks89-angular-modal-gallery.mjs} +3046 -2947
- package/fesm2020/ks89-angular-modal-gallery.mjs.map +1 -0
- package/ks89-angular-modal-gallery.d.ts +1 -24
- package/lib/components/accessible.component.d.ts +5 -2
- package/lib/components/carousel/carousel-previews/carousel-previews.component.d.ts +7 -11
- package/lib/components/carousel/carousel.component.d.ts +28 -67
- package/lib/components/current-image/current-image.component.d.ts +10 -4
- package/lib/components/current-image/loading-spinner/loading-spinner.component.d.ts +3 -0
- package/lib/components/dots/dots.component.d.ts +7 -0
- package/lib/components/modal-gallery/modal-gallery-ref.d.ts +35 -0
- package/lib/components/modal-gallery/modal-gallery.component.d.ts +58 -50
- package/lib/components/modal-gallery/modal-gallery.service.d.ts +60 -1
- package/lib/components/plain-gallery/plain-gallery.component.d.ts +18 -9
- package/lib/components/previews/previews.component.d.ts +9 -0
- package/lib/components/upper-buttons/upper-buttons.component.d.ts +8 -1
- package/lib/directives/a-tag-bg-image.directive.d.ts +3 -0
- package/lib/directives/click-outside.directive.d.ts +3 -0
- package/lib/directives/description.directive.d.ts +3 -0
- package/lib/directives/direction.directive.d.ts +3 -0
- package/lib/directives/fallback-image.directive.d.ts +6 -0
- package/lib/directives/keyboard-navigation.directive.d.ts +4 -1
- package/lib/directives/margin.directive.d.ts +3 -0
- package/lib/directives/max-size.directive.d.ts +3 -0
- package/lib/directives/size.directive.d.ts +5 -2
- package/lib/directives/wrap.directive.d.ts +4 -1
- package/lib/modal-gallery.module.d.ts +28 -0
- package/lib/model/carousel-config.interface.d.ts +0 -1
- package/lib/model/keyboard-config.interface.d.ts +4 -4
- package/lib/model/keyboard.enum.d.ts +11 -8
- package/lib/model/lib-config.interface.d.ts +20 -7
- package/lib/model/modal-gallery-config.interface.d.ts +2 -2
- package/lib/model/plain-gallery-config.interface.d.ts +1 -9
- package/lib/services/config.service.d.ts +3 -0
- package/lib/services/id-validator.service.d.ts +5 -1
- package/lib/services/keyboard.service.d.ts +5 -2
- package/lib/utils/user-input.util.d.ts +35 -26
- package/package.json +28 -16
- package/public-api.d.ts +2 -2
- package/bundles/ks89-angular-modal-gallery.umd.js +0 -5906
- package/bundles/ks89-angular-modal-gallery.umd.js.map +0 -1
- package/bundles/ks89-angular-modal-gallery.umd.min.js +0 -16
- package/bundles/ks89-angular-modal-gallery.umd.min.js.map +0 -1
- package/esm2015/ks89-angular-modal-gallery.js +0 -29
- package/esm2015/lib/components/accessibility-default.js +0 -41
- package/esm2015/lib/components/accessible.component.js +0 -127
- package/esm2015/lib/components/carousel/carousel-previews/carousel-previews.component.js +0 -466
- package/esm2015/lib/components/carousel/carousel.component.js +0 -772
- package/esm2015/lib/components/components.js +0 -50
- package/esm2015/lib/components/current-image/current-image.component.js +0 -590
- package/esm2015/lib/components/current-image/loading-spinner/loading-spinner.component.js +0 -80
- package/esm2015/lib/components/dots/dots.component.js +0 -127
- package/esm2015/lib/components/modal-gallery/modal-gallery-ref.js +0 -45
- package/esm2015/lib/components/modal-gallery/modal-gallery.component.js +0 -534
- package/esm2015/lib/components/modal-gallery/modal-gallery.service.js +0 -135
- package/esm2015/lib/components/modal-gallery/modal-gallery.tokens.js +0 -3
- package/esm2015/lib/components/plain-gallery/plain-gallery.component.js +0 -243
- package/esm2015/lib/components/previews/previews.component.js +0 -331
- package/esm2015/lib/components/upper-buttons/upper-buttons-default.js +0 -76
- package/esm2015/lib/components/upper-buttons/upper-buttons.component.js +0 -256
- package/esm2015/lib/directives/a-tag-bg-image.directive.js +0 -78
- package/esm2015/lib/directives/click-outside.directive.js +0 -85
- package/esm2015/lib/directives/description.directive.js +0 -99
- package/esm2015/lib/directives/direction.directive.js +0 -73
- package/esm2015/lib/directives/directives.js +0 -49
- package/esm2015/lib/directives/fallback-image.directive.js +0 -54
- package/esm2015/lib/directives/keyboard-navigation.directive.js +0 -52
- package/esm2015/lib/directives/margin.directive.js +0 -82
- package/esm2015/lib/directives/max-size.directive.js +0 -76
- package/esm2015/lib/directives/wrap.directive.js +0 -74
- package/esm2015/lib/modal-gallery.module.js +0 -64
- package/esm2015/lib/model/accessibility.interface.js +0 -25
- package/esm2015/lib/model/action.enum.js +0 -36
- package/esm2015/lib/model/buttons-config.interface.js +0 -66
- package/esm2015/lib/model/carousel-image-config.interface.js +0 -25
- package/esm2015/lib/model/current-image-config.interface.js +0 -25
- package/esm2015/lib/model/description.interface.js +0 -33
- package/esm2015/lib/model/image.class.js +0 -54
- package/esm2015/lib/model/interaction-event.interface.js +0 -2
- package/esm2015/lib/model/keyboard-config.interface.js +0 -25
- package/esm2015/lib/model/keyboard.enum.js +0 -35
- package/esm2015/lib/model/lib-config.interface.js +0 -25
- package/esm2015/lib/model/loading-config.interface.js +0 -37
- package/esm2015/lib/model/max-size.interface.js +0 -25
- package/esm2015/lib/model/modal-gallery-config.interface.js +0 -25
- package/esm2015/lib/model/plain-gallery-config.interface.js +0 -64
- package/esm2015/lib/model/play-config.interface.js +0 -25
- package/esm2015/lib/model/size.interface.js +0 -25
- package/esm2015/lib/model/slide-config.interface.js +0 -25
- package/esm2015/lib/services/config.service.js +0 -392
- package/esm2015/lib/services/id-validator.service.js +0 -71
- package/esm2015/lib/services/keyboard.service.js +0 -108
- package/esm2015/lib/utils/image.util.js +0 -48
- package/esm2015/lib/utils/user-input.util.js +0 -95
- package/esm2015/public-api.js +0 -46
- package/fesm2015/ks89-angular-modal-gallery.js.map +0 -1
- package/ks89-angular-modal-gallery.metadata.json +0 -1
|
@@ -1,534 +0,0 @@
|
|
|
1
|
-
import { ChangeDetectorRef, Component, HostListener, Inject, PLATFORM_ID, SecurityContext, ViewChild } from '@angular/core';
|
|
2
|
-
import { isPlatformBrowser, isPlatformServer } from '@angular/common';
|
|
3
|
-
import { DomSanitizer } from '@angular/platform-browser';
|
|
4
|
-
import { DIALOG_DATA } from './modal-gallery.tokens';
|
|
5
|
-
import { ImageModalEvent } from '../../model/image.class';
|
|
6
|
-
import { ConfigService } from '../../services/config.service';
|
|
7
|
-
import { Action } from '../../model/action.enum';
|
|
8
|
-
import { CurrentImageComponent } from '../current-image/current-image.component';
|
|
9
|
-
import { KeyboardService } from '../../services/keyboard.service';
|
|
10
|
-
import { IdValidatorService } from '../../services/id-validator.service';
|
|
11
|
-
import { KS_DEFAULT_ACCESSIBILITY_CONFIG } from '../accessibility-default';
|
|
12
|
-
import { ModalGalleryService } from './modal-gallery.service';
|
|
13
|
-
export class ModalGalleryComponent {
|
|
14
|
-
constructor(dialogContent, modalGalleryService, keyboardService,
|
|
15
|
-
// tslint:disable-next-line:ban-types
|
|
16
|
-
platformId, changeDetectorRef, idValidatorService, configService, sanitizer) {
|
|
17
|
-
this.dialogContent = dialogContent;
|
|
18
|
-
this.modalGalleryService = modalGalleryService;
|
|
19
|
-
this.keyboardService = keyboardService;
|
|
20
|
-
this.platformId = platformId;
|
|
21
|
-
this.changeDetectorRef = changeDetectorRef;
|
|
22
|
-
this.idValidatorService = idValidatorService;
|
|
23
|
-
this.configService = configService;
|
|
24
|
-
this.sanitizer = sanitizer;
|
|
25
|
-
/**
|
|
26
|
-
* Boolean to enable modal-gallery close behaviour when clicking
|
|
27
|
-
* on the semi-transparent background. Enabled by default.
|
|
28
|
-
*/
|
|
29
|
-
this.enableCloseOutside = true;
|
|
30
|
-
/**
|
|
31
|
-
* Object of type `AccessibilityConfig` to init custom accessibility features.
|
|
32
|
-
* For instance, it contains titles, alt texts, aria-labels and so on.
|
|
33
|
-
*/
|
|
34
|
-
this.accessibilityConfig = KS_DEFAULT_ACCESSIBILITY_CONFIG;
|
|
35
|
-
/**
|
|
36
|
-
* Boolean to open the modal gallery. False by default.
|
|
37
|
-
*/
|
|
38
|
-
this.showGallery = false;
|
|
39
|
-
this.id = this.dialogContent.id;
|
|
40
|
-
this.images = this.dialogContent.images;
|
|
41
|
-
this.currentImage = this.dialogContent.currentImage;
|
|
42
|
-
this.libConfig = this.dialogContent.libConfig;
|
|
43
|
-
this.configService.setConfig(this.id, this.libConfig);
|
|
44
|
-
this.updateImagesSubscription = this.modalGalleryService.updateImages$.subscribe((images) => {
|
|
45
|
-
this.images = images.map((image) => {
|
|
46
|
-
const newImage = Object.assign({}, image, { previouslyLoaded: false });
|
|
47
|
-
return newImage;
|
|
48
|
-
});
|
|
49
|
-
this.initImages();
|
|
50
|
-
this.images.forEach((image) => {
|
|
51
|
-
if (image.id === this.currentImage.id) {
|
|
52
|
-
this.currentImage = image;
|
|
53
|
-
}
|
|
54
|
-
});
|
|
55
|
-
this.changeDetectorRef.markForCheck();
|
|
56
|
-
});
|
|
57
|
-
}
|
|
58
|
-
/**
|
|
59
|
-
* HostListener to catch browser's back button and destroy the gallery.
|
|
60
|
-
* This prevents weired behaviour about scrolling.
|
|
61
|
-
* Added to fix this issue: https://github.com/Ks89/angular-modal-gallery/issues/159
|
|
62
|
-
*/
|
|
63
|
-
onPopState(e) {
|
|
64
|
-
this.closeGallery();
|
|
65
|
-
}
|
|
66
|
-
/**
|
|
67
|
-
* Method ´ngOnInit´ to init images calling `initImages()`.
|
|
68
|
-
* This is an Angular's lifecycle hook, so its called automatically by Angular itself.
|
|
69
|
-
* In particular, it's called only one time!!!
|
|
70
|
-
*/
|
|
71
|
-
ngOnInit() {
|
|
72
|
-
this.idValidatorService.checkAndAdd(this.id);
|
|
73
|
-
// id is a mandatory input and must a number > 0
|
|
74
|
-
if ((!this.id && this.id !== 0) || this.id < 0) {
|
|
75
|
-
throw new Error(`'[id]="a number >= 0"' is a mandatory input in angular-modal-gallery.` +
|
|
76
|
-
`If you are using multiple instances of this library, please be sure to use different ids`);
|
|
77
|
-
}
|
|
78
|
-
const libConfig = this.configService.getConfig(this.id);
|
|
79
|
-
if (!libConfig || !libConfig.dotsConfig) {
|
|
80
|
-
throw new Error('Internal library error - libConfig and dotsConfig must be defined');
|
|
81
|
-
}
|
|
82
|
-
this.dotsConfig = libConfig.dotsConfig;
|
|
83
|
-
// call initImages to init images and to emit `hasData` event
|
|
84
|
-
this.initImages();
|
|
85
|
-
this.showModalGallery();
|
|
86
|
-
}
|
|
87
|
-
/**
|
|
88
|
-
* Method called by custom upper buttons.
|
|
89
|
-
* @param event ButtonEvent payload
|
|
90
|
-
*/
|
|
91
|
-
onCustomEmit(event) {
|
|
92
|
-
const eventToEmit = this.getButtonEventToEmit(event);
|
|
93
|
-
this.modalGalleryService.emitButtonBeforeHook(eventToEmit);
|
|
94
|
-
this.modalGalleryService.emitButtonAfterHook(eventToEmit);
|
|
95
|
-
}
|
|
96
|
-
/**
|
|
97
|
-
* Method called by the full-screen upper button.
|
|
98
|
-
* @param ButtonEvent event payload
|
|
99
|
-
*/
|
|
100
|
-
onFullScreen(event) {
|
|
101
|
-
const eventToEmit = this.getButtonEventToEmit(event);
|
|
102
|
-
this.modalGalleryService.emitButtonBeforeHook(eventToEmit);
|
|
103
|
-
// tslint:disable-next-line:no-any
|
|
104
|
-
const doc = document;
|
|
105
|
-
// tslint:disable-next-line:no-any
|
|
106
|
-
const docEl = document.documentElement;
|
|
107
|
-
const fullscreenDisabled = !doc.fullscreenElement && !doc.webkitFullscreenElement && !doc.mozFullScreenElement && !doc.msFullscreenElement;
|
|
108
|
-
if (fullscreenDisabled) {
|
|
109
|
-
if (docEl.requestFullscreen) {
|
|
110
|
-
docEl.requestFullscreen();
|
|
111
|
-
}
|
|
112
|
-
else if (docEl.webkitRequestFullscreen) {
|
|
113
|
-
docEl.webkitRequestFullscreen();
|
|
114
|
-
}
|
|
115
|
-
else if (docEl.mozRequestFullScreen) {
|
|
116
|
-
docEl.mozRequestFullScreen();
|
|
117
|
-
}
|
|
118
|
-
else if (docEl.msRequestFullscreen) {
|
|
119
|
-
docEl.msRequestFullscreen();
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
else {
|
|
123
|
-
if (doc.exitFullscreen) {
|
|
124
|
-
doc.exitFullscreen();
|
|
125
|
-
}
|
|
126
|
-
else if (doc.msExitFullscreen) {
|
|
127
|
-
doc.msExitFullscreen();
|
|
128
|
-
}
|
|
129
|
-
else if (doc.mozCancelFullScreen) {
|
|
130
|
-
doc.mozCancelFullScreen();
|
|
131
|
-
}
|
|
132
|
-
else if (doc.webkitExitFullscreen) {
|
|
133
|
-
doc.webkitExitFullscreen();
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
this.modalGalleryService.emitButtonAfterHook(eventToEmit);
|
|
137
|
-
}
|
|
138
|
-
/**
|
|
139
|
-
* Method called by the delete upper button.
|
|
140
|
-
* @param ButtonEvent event payload
|
|
141
|
-
*/
|
|
142
|
-
onDelete(event) {
|
|
143
|
-
const eventToEmit = this.getButtonEventToEmit(event);
|
|
144
|
-
this.modalGalleryService.emitButtonBeforeHook(eventToEmit);
|
|
145
|
-
if (this.images.length === 1) {
|
|
146
|
-
this.closeGallery();
|
|
147
|
-
}
|
|
148
|
-
if (!this.currentImageComponent) {
|
|
149
|
-
throw new Error('currentImageComponent must be defined');
|
|
150
|
-
}
|
|
151
|
-
const imageIndexToDelete = this.currentImageComponent.getIndexToDelete(event.image);
|
|
152
|
-
if (imageIndexToDelete === this.images.length - 1) {
|
|
153
|
-
// last image
|
|
154
|
-
this.currentImageComponent.prevImage();
|
|
155
|
-
}
|
|
156
|
-
else {
|
|
157
|
-
this.currentImageComponent.nextImage();
|
|
158
|
-
}
|
|
159
|
-
this.modalGalleryService.emitButtonAfterHook(eventToEmit);
|
|
160
|
-
}
|
|
161
|
-
/**
|
|
162
|
-
* Method called by the navigate upper button.
|
|
163
|
-
* @param ButtonEvent event payload
|
|
164
|
-
*/
|
|
165
|
-
onNavigate(event) {
|
|
166
|
-
const eventToEmit = this.getButtonEventToEmit(event);
|
|
167
|
-
this.modalGalleryService.emitButtonBeforeHook(eventToEmit);
|
|
168
|
-
// To support SSR
|
|
169
|
-
if (isPlatformBrowser(this.platformId)) {
|
|
170
|
-
if (eventToEmit.image && eventToEmit.image.modal.extUrl) {
|
|
171
|
-
// where I should open this link? The current tab or another one?
|
|
172
|
-
if (eventToEmit.button && eventToEmit.button.extUrlInNewTab) {
|
|
173
|
-
// in this case I should use target _blank to open the url in a new tab, however these is a security issue.
|
|
174
|
-
// Prevent Reverse Tabnabbing's attacks (https://www.owasp.org/index.php/Reverse_Tabnabbing)
|
|
175
|
-
// Some resources:
|
|
176
|
-
// - https://www.owasp.org/index.php/HTML5_Security_Cheat_Sheet#Tabnabbing
|
|
177
|
-
// - https://medium.com/@jitbit/target-blank-the-most-underestimated-vulnerability-ever-96e328301f4c
|
|
178
|
-
// - https://developer.mozilla.org/en-US/docs/Web/API/Window/open
|
|
179
|
-
const newWindow = window.open(eventToEmit.image.modal.extUrl, 'noopener,noreferrer,');
|
|
180
|
-
// it returns null if the call failed, so I have to do this check
|
|
181
|
-
if (newWindow) {
|
|
182
|
-
newWindow.opener = null; // required to prevent security issues
|
|
183
|
-
// emit only in case of success
|
|
184
|
-
this.modalGalleryService.emitButtonAfterHook(eventToEmit);
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
else {
|
|
188
|
-
window.location.href = eventToEmit.image.modal.extUrl;
|
|
189
|
-
// emit only in case of success
|
|
190
|
-
this.modalGalleryService.emitButtonAfterHook(eventToEmit);
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
/**
|
|
196
|
-
* Method called by the download upper button.
|
|
197
|
-
* @param ButtonEvent event payload
|
|
198
|
-
*/
|
|
199
|
-
onDownload(event) {
|
|
200
|
-
const eventToEmit = this.getButtonEventToEmit(event);
|
|
201
|
-
this.modalGalleryService.emitButtonBeforeHook(eventToEmit);
|
|
202
|
-
this.downloadImage();
|
|
203
|
-
this.modalGalleryService.emitButtonAfterHook(eventToEmit);
|
|
204
|
-
}
|
|
205
|
-
/**
|
|
206
|
-
* Method called by the close upper button.
|
|
207
|
-
* @param ButtonEvent event payload
|
|
208
|
-
* @param Action action that triggered the close method. `Action.NORMAL` by default
|
|
209
|
-
*/
|
|
210
|
-
onCloseGallery(event, action = Action.NORMAL) {
|
|
211
|
-
const eventToEmit = this.getButtonEventToEmit(event);
|
|
212
|
-
this.modalGalleryService.emitButtonBeforeHook(eventToEmit);
|
|
213
|
-
this.closeGallery(action, false);
|
|
214
|
-
this.modalGalleryService.emitButtonAfterHook(eventToEmit);
|
|
215
|
-
}
|
|
216
|
-
/**
|
|
217
|
-
* Method to close the modal gallery specifying the action.
|
|
218
|
-
* It also reset the `keyboardService` to prevent multiple listeners.
|
|
219
|
-
* @param Action action type. `Action.NORMAL` by default
|
|
220
|
-
* @param boolean isCalledByService is true if called by gallery.service, otherwise false
|
|
221
|
-
*/
|
|
222
|
-
closeGallery(action = Action.NORMAL, clickOutside = false, isCalledByService = false) {
|
|
223
|
-
const libConfig = this.configService.getConfig(this.id);
|
|
224
|
-
if (!libConfig) {
|
|
225
|
-
throw new Error('Internal library error - libConfig must be defined');
|
|
226
|
-
}
|
|
227
|
-
this.modalGalleryService.emitClose(new ImageModalEvent(this.id, action, true));
|
|
228
|
-
this.keyboardService.reset(libConfig);
|
|
229
|
-
this.modalGalleryService.close(this.id, clickOutside);
|
|
230
|
-
// shows scrollbar
|
|
231
|
-
document.body.style.overflow = 'visible';
|
|
232
|
-
if (isCalledByService) {
|
|
233
|
-
// the following is required, otherwise the view will not be updated
|
|
234
|
-
// this happens only if called by gallery.service
|
|
235
|
-
this.changeDetectorRef.markForCheck();
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
|
-
/**
|
|
239
|
-
* Method to show the modal gallery displaying the image with
|
|
240
|
-
* the index specified as input parameter.
|
|
241
|
-
* It will also register a new `keyboardService` to catch keyboard's events to download the current
|
|
242
|
-
* image with keyboard's shortcuts. This service, will be removed either when modal gallery component
|
|
243
|
-
* will be destroyed or when the gallery is closed invoking the `closeGallery` method.
|
|
244
|
-
* @param number index of the image to show
|
|
245
|
-
*/
|
|
246
|
-
showModalGallery() {
|
|
247
|
-
// hides scrollbar
|
|
248
|
-
document.body.style.overflow = 'hidden';
|
|
249
|
-
if (!this.id) {
|
|
250
|
-
throw new Error('Internal library error - id must be defined');
|
|
251
|
-
}
|
|
252
|
-
const libConfig = this.configService.getConfig(this.id);
|
|
253
|
-
if (!libConfig) {
|
|
254
|
-
throw new Error('Internal library error - libConfig must be defined');
|
|
255
|
-
}
|
|
256
|
-
this.keyboardService.init(libConfig).then(() => {
|
|
257
|
-
this.keyboardService.add((event, combo) => {
|
|
258
|
-
if (event.preventDefault) {
|
|
259
|
-
event.preventDefault();
|
|
260
|
-
}
|
|
261
|
-
else {
|
|
262
|
-
// internet explorer
|
|
263
|
-
event.returnValue = false;
|
|
264
|
-
}
|
|
265
|
-
this.downloadImage();
|
|
266
|
-
}, libConfig);
|
|
267
|
-
const currentIndex = this.images.indexOf(this.currentImage);
|
|
268
|
-
// emit a new ImageModalEvent with the index of the current image
|
|
269
|
-
this.modalGalleryService.emitShow(new ImageModalEvent(this.id, Action.LOAD, currentIndex + 1));
|
|
270
|
-
this.changeDetectorRef.markForCheck();
|
|
271
|
-
});
|
|
272
|
-
}
|
|
273
|
-
/**
|
|
274
|
-
* Method called when the image changes and used to update the `currentImage` object.
|
|
275
|
-
* @param ImageModalEvent event payload
|
|
276
|
-
*/
|
|
277
|
-
onChangeCurrentImage(event) {
|
|
278
|
-
const newIndex = event.result;
|
|
279
|
-
if (newIndex < 0 || newIndex >= this.images.length) {
|
|
280
|
-
return;
|
|
281
|
-
}
|
|
282
|
-
this.currentImage = this.images[newIndex];
|
|
283
|
-
// emit first/last event based on newIndex value
|
|
284
|
-
this.emitBoundaryEvent(event.action, newIndex);
|
|
285
|
-
// emit current visible image index
|
|
286
|
-
this.modalGalleryService.emitShow(new ImageModalEvent(this.id, event.action, newIndex + 1));
|
|
287
|
-
}
|
|
288
|
-
/**
|
|
289
|
-
* Method called when you click 'outside' (i.e. on the semi-transparent background)
|
|
290
|
-
* to close the modal gallery if `enableCloseOutside` is true.
|
|
291
|
-
* @param boolean event payload. True to close the modal gallery, false otherwise
|
|
292
|
-
*/
|
|
293
|
-
onClickOutside(event) {
|
|
294
|
-
if (event && this.enableCloseOutside) {
|
|
295
|
-
this.closeGallery(Action.CLICK, true);
|
|
296
|
-
}
|
|
297
|
-
}
|
|
298
|
-
/**
|
|
299
|
-
* Method called when an image is loaded and the loading spinner has gone.
|
|
300
|
-
* It sets the previouslyLoaded flag inside the Image to hide loading spinner when displayed again.
|
|
301
|
-
* @param ImageLoadEvent event payload
|
|
302
|
-
*/
|
|
303
|
-
onImageLoad(event) {
|
|
304
|
-
// sets as previously loaded the image with index specified by `event.status`
|
|
305
|
-
this.images = this.images.map((img) => {
|
|
306
|
-
if (img && img.id === event.id) {
|
|
307
|
-
return Object.assign({}, img, { previouslyLoaded: event.status });
|
|
308
|
-
}
|
|
309
|
-
return img;
|
|
310
|
-
});
|
|
311
|
-
}
|
|
312
|
-
/**
|
|
313
|
-
* Method called when a dot is clicked and used to update the current image.
|
|
314
|
-
* @param number index of the clicked dot
|
|
315
|
-
*/
|
|
316
|
-
onClickDot(index) {
|
|
317
|
-
this.currentImage = this.images[index];
|
|
318
|
-
}
|
|
319
|
-
/**
|
|
320
|
-
* Method called when an image preview is clicked and used to update the current image.
|
|
321
|
-
* @param Image preview image
|
|
322
|
-
*/
|
|
323
|
-
onClickPreview(event) {
|
|
324
|
-
this.onChangeCurrentImage(event);
|
|
325
|
-
}
|
|
326
|
-
/**
|
|
327
|
-
* Method to download the current image, only if `downloadable` is true.
|
|
328
|
-
* It contains also a logic to enable downloading features also for IE11.
|
|
329
|
-
*/
|
|
330
|
-
downloadImage() {
|
|
331
|
-
if (!this.id) {
|
|
332
|
-
throw new Error('Internal library error - id must be defined');
|
|
333
|
-
}
|
|
334
|
-
const libConfig = this.configService.getConfig(this.id);
|
|
335
|
-
if (!libConfig) {
|
|
336
|
-
throw new Error('Internal library error - libConfig must be defined');
|
|
337
|
-
}
|
|
338
|
-
const currentImageConfig = libConfig.currentImageConfig;
|
|
339
|
-
if (currentImageConfig && !currentImageConfig.downloadable) {
|
|
340
|
-
return;
|
|
341
|
-
}
|
|
342
|
-
// If IE11 or Microsoft Edge use msSaveBlob(...)
|
|
343
|
-
if (this.isIEorEdge()) {
|
|
344
|
-
// I cannot use fetch API because IE11 doesn't support it,
|
|
345
|
-
// so I have to switch to XMLHttpRequest
|
|
346
|
-
this.downloadImageOnlyIEorEdge();
|
|
347
|
-
}
|
|
348
|
-
else {
|
|
349
|
-
// for all other browsers
|
|
350
|
-
this.downloadImageAllBrowsers();
|
|
351
|
-
}
|
|
352
|
-
}
|
|
353
|
-
/**
|
|
354
|
-
* Method to cleanup resources. In fact, this will reset keyboard's service.
|
|
355
|
-
* This is an Angular's lifecycle hook that is called when this component is destroyed.
|
|
356
|
-
*/
|
|
357
|
-
ngOnDestroy() {
|
|
358
|
-
if (this.keyboardService) {
|
|
359
|
-
const libConfig = this.configService.getConfig(this.id);
|
|
360
|
-
if (this.id && libConfig) {
|
|
361
|
-
this.keyboardService.reset(libConfig);
|
|
362
|
-
}
|
|
363
|
-
}
|
|
364
|
-
if (this.updateImagesSubscription) {
|
|
365
|
-
this.updateImagesSubscription.unsubscribe();
|
|
366
|
-
}
|
|
367
|
-
this.idValidatorService.remove(this.id);
|
|
368
|
-
}
|
|
369
|
-
/**
|
|
370
|
-
* Method to convert a base64 to a Blob
|
|
371
|
-
* @param base64Data string with base64 data
|
|
372
|
-
* @param contentType string with the MIME type
|
|
373
|
-
*/
|
|
374
|
-
base64toBlob(base64Data, contentType = '') {
|
|
375
|
-
const sliceSize = 1024;
|
|
376
|
-
const byteCharacters = atob(base64Data);
|
|
377
|
-
const bytesLength = byteCharacters.length;
|
|
378
|
-
const slicesCount = Math.ceil(bytesLength / sliceSize);
|
|
379
|
-
const byteArrays = new Array(slicesCount);
|
|
380
|
-
for (let sliceIndex = 0; sliceIndex < slicesCount; ++sliceIndex) {
|
|
381
|
-
const begin = sliceIndex * sliceSize;
|
|
382
|
-
const end = Math.min(begin + sliceSize, bytesLength);
|
|
383
|
-
const bytes = new Array(end - begin);
|
|
384
|
-
for (let offset = begin, i = 0; offset < end; ++i, ++offset) {
|
|
385
|
-
bytes[i] = byteCharacters[offset].charCodeAt(0);
|
|
386
|
-
}
|
|
387
|
-
byteArrays[sliceIndex] = new Uint8Array(bytes);
|
|
388
|
-
}
|
|
389
|
-
return new Blob(byteArrays, { type: contentType });
|
|
390
|
-
}
|
|
391
|
-
/**
|
|
392
|
-
* Private method to download the current image for all browsers except for IE11.
|
|
393
|
-
*/
|
|
394
|
-
downloadImageAllBrowsers() {
|
|
395
|
-
const link = document.createElement('a');
|
|
396
|
-
let isBase64 = false;
|
|
397
|
-
let img;
|
|
398
|
-
// convert a SafeResourceUrl to a string
|
|
399
|
-
if (typeof this.currentImage.modal.img === 'string') {
|
|
400
|
-
img = this.currentImage.modal.img;
|
|
401
|
-
}
|
|
402
|
-
else {
|
|
403
|
-
// if it's a SafeResourceUrl
|
|
404
|
-
img = this.sanitizer.sanitize(SecurityContext.RESOURCE_URL, this.currentImage.modal.img);
|
|
405
|
-
}
|
|
406
|
-
if (img.includes('data:image/') || img.includes(';base64,')) {
|
|
407
|
-
const extension = img.replace('data:image/', '').split(';base64,')[0];
|
|
408
|
-
const pureBase64 = img.split(';base64,')[1];
|
|
409
|
-
const blob = this.base64toBlob(pureBase64, 'image/' + extension);
|
|
410
|
-
link.href = URL.createObjectURL(blob);
|
|
411
|
-
isBase64 = true;
|
|
412
|
-
link.setAttribute('download', this.getFileName(this.currentImage, isBase64, extension));
|
|
413
|
-
}
|
|
414
|
-
else {
|
|
415
|
-
link.href = img;
|
|
416
|
-
link.setAttribute('download', this.getFileName(this.currentImage, isBase64));
|
|
417
|
-
}
|
|
418
|
-
document.body.appendChild(link);
|
|
419
|
-
link.click();
|
|
420
|
-
document.body.removeChild(link);
|
|
421
|
-
}
|
|
422
|
-
/**
|
|
423
|
-
* Private method to download the current image only for IE11 using
|
|
424
|
-
* custom javascript's methods available only on IE.
|
|
425
|
-
*/
|
|
426
|
-
downloadImageOnlyIEorEdge() {
|
|
427
|
-
if (isPlatformBrowser(this.platformId)) {
|
|
428
|
-
const req = new XMLHttpRequest();
|
|
429
|
-
req.open('GET', this.currentImage.modal.img, true);
|
|
430
|
-
req.responseType = 'arraybuffer';
|
|
431
|
-
req.onload = event => {
|
|
432
|
-
const blob = new Blob([req.response], { type: 'image/png' });
|
|
433
|
-
window.navigator.msSaveBlob(blob, this.getFileName(this.currentImage));
|
|
434
|
-
};
|
|
435
|
-
req.send();
|
|
436
|
-
}
|
|
437
|
-
}
|
|
438
|
-
/**
|
|
439
|
-
* Private method to get the `ButtonEvent` to emit, merging the input `ButtonEvent`
|
|
440
|
-
* with the current image.
|
|
441
|
-
* @param ButtonEvent event payload to return
|
|
442
|
-
* @returns ButtonEvent event payload with the current image included
|
|
443
|
-
*/
|
|
444
|
-
getButtonEventToEmit(event) {
|
|
445
|
-
return Object.assign(event, { image: this.currentImage });
|
|
446
|
-
}
|
|
447
|
-
/**
|
|
448
|
-
* Private method to get the file name from an input path.
|
|
449
|
-
* This is used either to get the image's name from its path or from the Image itself,
|
|
450
|
-
* if specified as 'downloadFileName' by the user.
|
|
451
|
-
* @param Image image to extract its file name
|
|
452
|
-
* @param isBase64 boolean to set if the image is a base64 file or not. False by default.
|
|
453
|
-
* @param base64Extension string to force the extension of the base64 image. Empty string by default.
|
|
454
|
-
* @returns string string file name of the input image.
|
|
455
|
-
*/
|
|
456
|
-
getFileName(image, isBase64 = false, base64Extension = '') {
|
|
457
|
-
if (!image.modal.downloadFileName || image.modal.downloadFileName.length === 0) {
|
|
458
|
-
if (isBase64) {
|
|
459
|
-
return `Image-${image.id}.${base64Extension !== '' ? base64Extension : 'png'}`;
|
|
460
|
-
}
|
|
461
|
-
else {
|
|
462
|
-
return image.modal.img.replace(/^.*[\\\/]/, '');
|
|
463
|
-
}
|
|
464
|
-
}
|
|
465
|
-
else {
|
|
466
|
-
return image.modal.downloadFileName;
|
|
467
|
-
}
|
|
468
|
-
}
|
|
469
|
-
/**
|
|
470
|
-
* Private method to initialize `images` as array of `Image`s.
|
|
471
|
-
* Also, it will emit ImageowmodaModalEvent to say that images are loaded.
|
|
472
|
-
*/
|
|
473
|
-
initImages() {
|
|
474
|
-
this.modalGalleryService.emitHasData(new ImageModalEvent(this.id, Action.LOAD, true));
|
|
475
|
-
this.showGallery = this.images.length > 0;
|
|
476
|
-
}
|
|
477
|
-
/**
|
|
478
|
-
* Private method to emit events when either the last or the first image are visible.
|
|
479
|
-
* @param action Enum of type Action that represents the source of the event that changed the
|
|
480
|
-
* current image to the first one or the last one.
|
|
481
|
-
* @param indexToCheck is the index number of the image (the first or the last one).
|
|
482
|
-
*/
|
|
483
|
-
emitBoundaryEvent(action, indexToCheck) {
|
|
484
|
-
// to emit first/last event
|
|
485
|
-
switch (indexToCheck) {
|
|
486
|
-
case 0:
|
|
487
|
-
this.modalGalleryService.emitFirstImage(new ImageModalEvent(this.id, action, true));
|
|
488
|
-
break;
|
|
489
|
-
case this.images.length - 1:
|
|
490
|
-
this.modalGalleryService.emitLastImage(new ImageModalEvent(this.id, action, true));
|
|
491
|
-
break;
|
|
492
|
-
}
|
|
493
|
-
}
|
|
494
|
-
/**
|
|
495
|
-
* Private method to check if this library is running on
|
|
496
|
-
* Microsoft browsers or not (i.e. it detects both IE11 and Edge)
|
|
497
|
-
* supporting also Server-Side Rendering.
|
|
498
|
-
* Inspired by https://msdn.microsoft.com/it-it/library/hh779016(v=vs.85).aspx
|
|
499
|
-
* @returns any the result
|
|
500
|
-
*/
|
|
501
|
-
isIEorEdge() {
|
|
502
|
-
if (isPlatformBrowser(this.platformId)) {
|
|
503
|
-
// if both Blob constructor and msSaveOrOpenBlob are supported by the current browser
|
|
504
|
-
return !!window.Blob && !!window.navigator.msSaveOrOpenBlob;
|
|
505
|
-
}
|
|
506
|
-
if (isPlatformServer(this.platformId)) {
|
|
507
|
-
// server only
|
|
508
|
-
return true;
|
|
509
|
-
}
|
|
510
|
-
return false;
|
|
511
|
-
}
|
|
512
|
-
}
|
|
513
|
-
ModalGalleryComponent.decorators = [
|
|
514
|
-
{ type: Component, args: [{
|
|
515
|
-
selector: 'ks-modal-gallery',
|
|
516
|
-
template: "<div id=\"modal-gallery-wrapper\"\n [attr.aria-label]=\"accessibilityConfig.modalGalleryContentAriaLabel\"\n [title]=\"accessibilityConfig.modalGalleryContentTitle\"\n ksClickOutside [clickOutsideEnable]=\"enableCloseOutside\"\n (clickOutside)=\"onClickOutside($event)\">\n\n <div id=\"flex-min-height-ie-fix\">\n <div id=\"modal-gallery-container\">\n\n <ks-upper-buttons [id]=\"id\"\n [currentImage]=\"currentImage\"\n (delete)=\"onDelete($event)\"\n (navigate)=\"onNavigate($event)\"\n (download)=\"onDownload($event)\"\n (closeButton)=\"onCloseGallery($event)\"\n (fullscreen)=\"onFullScreen($event)\"\n (customEmit)=\"onCustomEmit($event)\"></ks-upper-buttons>\n\n <ks-current-image [id]=\"id\"\n [images]=\"images\"\n [currentImage]=\"currentImage\"\n [isOpen]=\"true\"\n (loadImage)=\"onImageLoad($event)\"\n (changeImage)=\"onChangeCurrentImage($event)\"\n (closeGallery)=\"onCloseGallery($event)\"></ks-current-image>\n\n <div>\n <ks-dots [id]=\"id\"\n [images]=\"images\"\n [currentImage]=\"currentImage\"\n [dotsConfig]=\"dotsConfig\"\n (clickDot)=\"onClickDot($event)\"></ks-dots>\n\n <ks-previews [id]=\"id\"\n [images]=\"images\"\n [currentImage]=\"currentImage\"\n (clickPreview)=\"onClickPreview($event)\"></ks-previews>\n </div>\n </div>\n </div>\n</div>\n",
|
|
517
|
-
styles: ["#flex-min-height-ie-fix{display:flex;flex-direction:column;justify-content:center}#modal-gallery-container{display:flex;flex-direction:column;justify-content:space-between;min-height:100vh;min-width:100vw}"]
|
|
518
|
-
},] }
|
|
519
|
-
];
|
|
520
|
-
ModalGalleryComponent.ctorParameters = () => [
|
|
521
|
-
{ type: undefined, decorators: [{ type: Inject, args: [DIALOG_DATA,] }] },
|
|
522
|
-
{ type: ModalGalleryService },
|
|
523
|
-
{ type: KeyboardService },
|
|
524
|
-
{ type: Object, decorators: [{ type: Inject, args: [PLATFORM_ID,] }] },
|
|
525
|
-
{ type: ChangeDetectorRef },
|
|
526
|
-
{ type: IdValidatorService },
|
|
527
|
-
{ type: ConfigService },
|
|
528
|
-
{ type: DomSanitizer }
|
|
529
|
-
];
|
|
530
|
-
ModalGalleryComponent.propDecorators = {
|
|
531
|
-
currentImageComponent: [{ type: ViewChild, args: [CurrentImageComponent, { static: true },] }],
|
|
532
|
-
onPopState: [{ type: HostListener, args: ['window:popstate', ['$event'],] }]
|
|
533
|
-
};
|
|
534
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibW9kYWwtZ2FsbGVyeS5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiLi4vLi4vLi4vLi4vcHJvamVjdHMva3M4OS9hbmd1bGFyLW1vZGFsLWdhbGxlcnkvc3JjLyIsInNvdXJjZXMiOlsibGliL2NvbXBvbmVudHMvbW9kYWwtZ2FsbGVyeS9tb2RhbC1nYWxsZXJ5LmNvbXBvbmVudC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsU0FBUyxFQUFFLFlBQVksRUFBRSxNQUFNLEVBQXFCLFdBQVcsRUFBRSxlQUFlLEVBQUUsU0FBUyxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQy9JLE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQ3RFLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSwyQkFBMkIsQ0FBQztBQUl6RCxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sd0JBQXdCLENBQUM7QUFDckQsT0FBTyxFQUFTLGVBQWUsRUFBRSxNQUFNLHlCQUF5QixDQUFDO0FBQ2pFLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSwrQkFBK0IsQ0FBQztBQUk5RCxPQUFPLEVBQUUsTUFBTSxFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFDakQsT0FBTyxFQUFFLHFCQUFxQixFQUFrQixNQUFNLDBDQUEwQyxDQUFDO0FBQ2pHLE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSxpQ0FBaUMsQ0FBQztBQUNsRSxPQUFPLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSxxQ0FBcUMsQ0FBQztBQU16RSxPQUFPLEVBQUUsK0JBQStCLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQztBQUUzRSxPQUFPLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQVM5RCxNQUFNLE9BQU8scUJBQXFCO0lBNkVoQyxZQUMrQixhQUFpQyxFQUN0RCxtQkFBd0MsRUFDeEMsZUFBZ0M7SUFDeEMscUNBQXFDO0lBQ1IsVUFBa0Is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SSxDQUFDLE1BQU0sQ0FBQyxNQUFNLEdBQUcsQ0FBQztnQkFDekIsSUFBSSxDQUFDLG1CQUFtQixDQUFDLGFBQWEsQ0FBQyxJQUFJLGVBQWUsQ0FBQyxJQUFJLENBQUMsRUFBRSxFQUFFLE1BQU0sRUFBRSxJQUFJLENBQUMsQ0FBQyxDQUFDO2dCQUNuRixNQUFNO1NBQ1Q7SUFDSCxDQUFDO0lBRUQ7Ozs7OztPQU1HO0lBQ0ssVUFBVTtRQUNoQixJQUFJLGlCQUFpQixDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsRUFBRTtZQUN0QyxxRkFBcUY7WUFDckYsT0FBTyxDQUFDLENBQUMsTUFBTSxDQUFDLElBQUksSUFBSSxDQUFDLENBQUMsTUFBTSxDQUFDLFNBQVMsQ0FBQyxnQkFBZ0IsQ0FBQztTQUM3RDtRQUNELElBQUksZ0JBQWdCLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxFQUFFO1lBQ3JDLGNBQWM7WUFDZCxPQUFPLElBQUksQ0FBQztTQUNiO1FBQ0QsT0FBTyxLQUFLLENBQUM7SUFDZixDQUFDOzs7WUEva0JGLFNBQVMsU0FBQztnQkFDVCxRQUFRLEVBQUUsa0JBQWtCO2dCQUM1QixzdURBQTZDOzthQUU5Qzs7OzRDQStFSSxNQUFNLFNBQUMsV0FBVztZQXZGZCxtQkFBbUI7WUFUbkIsZUFBZTtZQW9HcUIsTUFBTSx1QkFBOUMsTUFBTSxTQUFDLFdBQVc7WUFsSGQsaUJBQWlCO1lBZWpCLGtCQUFrQjtZQVBsQixhQUFhO1lBTmIsWUFBWTs7O29DQWtDbEIsU0FBUyxTQUFDLHFCQUFxQixFQUFFLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBRTt5QkFvRWpELFlBQVksU0FBQyxpQkFBaUIsRUFBRSxDQUFDLFFBQVEsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IENoYW5nZURldGVjdG9yUmVmLCBDb21wb25lbnQsIEhvc3RMaXN0ZW5lciwgSW5qZWN0LCBPbkRlc3Ryb3ksIE9uSW5pdCwgUExBVEZPUk1fSUQsIFNlY3VyaXR5Q29udGV4dCwgVmlld0NoaWxkIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBpc1BsYXRmb3JtQnJvd3NlciwgaXNQbGF0Zm9ybVNlcnZlciB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbic7XG5pbXBvcnQgeyBEb21TYW5pdGl6ZXIgfSBmcm9tICdAYW5ndWxhci9wbGF0Zm9ybS1icm93c2VyJztcblxuaW1wb3J0IHsgU3Vic2NyaXB0aW9uIH0gZnJvbSAncnhqcyc7XG5cbmltcG9ydCB7IERJQUxPR19EQVRBIH0gZnJvbSAnLi9tb2RhbC1nYWxsZXJ5LnRva2Vucyc7XG5pbXBvcnQgeyBJbWFnZSwgSW1hZ2VNb2RhbEV2ZW50IH0gZnJvbSAnLi4vLi4vbW9kZWwvaW1hZ2UuY2xhc3MnO1xuaW1wb3J0IHsgQ29uZmlnU2VydmljZSB9IGZyb20gJy4uLy4uL3NlcnZpY2VzL2NvbmZpZy5zZXJ2aWNlJztcbmltcG9ydCB7IERvdHNDb25maWcgfSBmcm9tICcuLi8uLi9tb2RlbC9kb3RzLWNvbmZpZy5pbnRlcmZhY2UnO1xuaW1wb3J0IHsgQnV0dG9uRXZlbnQsIEJ1dHRvbnNDb25maWcgfSBmcm9tICcuLi8uLi9tb2RlbC9idXR0b25zLWNvbmZpZy5pbnRlcmZhY2UnO1xuaW1wb3J0IHsgSW50ZXJuYWxMaWJJbWFnZSB9IGZyb20gJy4uLy4uL21vZGVsL2ltYWdlLWludGVybmFsLmNsYXNzJztcbmltcG9ydCB7IEFjdGlvbiB9IGZyb20gJy4uLy4uL21vZGVsL2FjdGlvbi5lbnVtJztcbmltcG9ydCB7IEN1cnJlbnRJbWFnZUNvbXBvbmVudCwgSW1hZ2VMb2FkRXZlbnQgfSBmcm9tICcuLi9jdXJyZW50LWltYWdlL2N1cnJlbnQtaW1hZ2UuY29tcG9uZW50JztcbmltcG9ydCB7IEtleWJvYXJkU2VydmljZSB9IGZyb20gJy4uLy4uL3NlcnZpY2VzL2tleWJvYXJkLnNlcnZpY2UnO1xuaW1wb3J0IHsgSWRWYWxpZGF0b3JTZXJ2aWNlIH0gZnJvbSAnLi4vLi4vc2VydmljZXMvaWQtdmFsaWRhdG9yLnNlcnZpY2UnO1xuaW1wb3J0IHsgS2V5Ym9hcmRDb25maWcgfSBmcm9tICcuLi8uLi9tb2RlbC9rZXlib2FyZC1jb25maWcuaW50ZXJmYWNlJztcbmltcG9ydCB7IFByZXZpZXdDb25maWcgfSBmcm9tICcuLi8uLi9tb2RlbC9wcmV2aWV3LWNvbmZpZy5pbnRlcmZhY2UnO1xuaW1wb3J0IHsgU2xpZGVDb25maWcgfSBmcm9tICcuLi8uLi9tb2RlbC9zbGlkZS1jb25maWcuaW50ZXJmYWNlJztcbmltcG9ydCB7IEFjY2Vzc2liaWxpdHlDb25maWcgfSBmcm9tICcuLi8uLi9tb2RlbC9hY2Nlc3NpYmlsaXR5LmludGVyZmFjZSc7XG5pbXBvcnQgeyBQbGFpbkdhbGxlcnlDb25maWcgfSBmcm9tICcuLi8uLi9tb2RlbC9wbGFpbi1nYWxsZXJ5LWNvbmZpZy5pbnRlcmZhY2UnO1xuaW1wb3J0IHsgS1NfREVGQVVMVF9BQ0NFU1NJQklMSVRZX0NPTkZJRyB9IGZyb20gJy4uL2FjY2Vzc2liaWxpdHktZGVmYXVsdCc7XG5pbXBvcnQgeyBDdXJyZW50SW1hZ2VDb25maWcgfSBmcm9tICcuLi8uLi9tb2RlbC9jdXJyZW50LWltYWdlLWNvbmZpZy5pbnRlcmZhY2UnO1xuaW1wb3J0IHsgTW9kYWxHYWxsZXJ5U2VydmljZSB9IGZyb20gJy4vbW9kYWwtZ2FsbGVyeS5zZXJ2aWNlJztcbmltcG9ydCB7IExpYkNvbmZpZyB9IGZyb20gJy4uLy4uL21vZGVsL2xpYi1jb25maWcuaW50ZXJmYWNlJztcbmltcG9ydCB7IE1vZGFsR2FsbGVyeUNvbmZpZyB9IGZyb20gJy4uLy4uL21vZGVsL21vZGFsLWdhbGxlcnktY29uZmlnLmludGVyZmFjZSc7XG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ2tzLW1vZGFsLWdhbGxlcnknLFxuICB0ZW1wbGF0ZVVybDogJy4vbW9kYWwtZ2FsbGVyeS5jb21wb25lbnQuaHRtbCcsXG4gIHN0eWxlVXJsczogWycuL21vZGFsLWdhbGxlcnkuY29tcG9uZW50LnNjc3MnXVxufSlcbmV4cG9ydCBjbGFzcyBNb2RhbEdhbGxlcnlDb21wb25lbnQgaW1wbGVtZW50cyBPbkluaXQsIE9uRGVzdHJveSB7XG4gIC8qKlxuICAgKiBSZWZlcmVuY2UgdG8gdGhlIEN1cnJlbnRJbWFnZUNvbXBvbmVudCB0byBpbnZva2UgbWV0aG9kcyBvbiBpdC5cbiAgICovXG4gIEBWaWV3Q2hpbGQoQ3VycmVudEltYWdlQ29tcG9uZW50LCB7IHN0YXRpYzogdHJ1ZSB9KSBjdXJyZW50SW1hZ2VDb21wb25lbnQ6IEN1cnJlbnRJbWFnZUNvbXBvbmVudCB8IHVuZGVmaW5lZDtcblxuICAvKipcbiAgICogVW5pcXVlIGlkICg+PTApIG9mIHRoZSBjdXJyZW50IGluc3RhbmNlIG9mIHRoaXMgbGlicmFyeS4gVGhpcyBpcyB1c2VmdWwgd2hlbiB5b3UgYXJlIHVzaW5nXG4gICAqIHRoZSBzZXJ2aWNlIHRvIGNhbGwgbW9kYWwgZ2FsbGVyeSB3aXRob3V0IG9wZW4gaXQgbWFudWFsbHkuXG4gICAqL1xuICBpZDogbnVtYmVyO1xuICAvKipcbiAgICogT2JqZWN0IG9mIHR5cGUgYEJ1dHRvbnNDb25maWdgIHRvIHNob3cvaGlkZSBidXR0b25zLlxuICAgKi9cbiAgYnV0dG9uc0NvbmZpZzogQnV0dG9uc0NvbmZpZyB8IHVuZGVmaW5lZDtcbiAgLyoqXG4gICAqIEJvb2xlYW4gdG8gZW5hYmxlIG1vZGFsLWdhbGxlcnkgY2xvc2UgYmVoYXZpb3VyIHdoZW4gY2xpY2tpbmdcbiAgICogb24gdGhlIHNlbWktdHJhbnNwYXJlbnQgYmFja2dyb3VuZC4gRW5hYmxlZCBieSBkZWZhdWx0LlxuICAgKi9cbiAgZW5hYmxlQ2xvc2VPdXRzaWRlID0gdHJ1ZTtcbiAgLyoqXG4gICAqIE9iamVjdCBvZiB0eXBlIGBEb3RzQ29uZmlnYCB0byBpbml0IERvdHNDb21wb25lbnQncyBmZWF0dXJlcy5cbiAgICogRm9yIGluc3RhbmNlLCBpdCBjb250YWlucyBhIHBhcmFtIHRvIHNob3cvaGlkZSBkb3RzLlxuICAgKi9cbiAgZG90c0NvbmZpZzogRG90c0NvbmZpZyB8IHVuZGVmaW5lZDtcbiAgLyoqXG4gICAqIE9iamVjdCBvZiB0eXBlIGBQcmV2aWV3Q29uZmlnYCB0byBpbml0IFByZXZpZXdzQ29tcG9uZW50J3MgZmVhdHVyZXMuXG4gICAqIEZvciBpbnN0YW5jZSwgaXQgY29udGFpbnMgYSBwYXJhbSB0byBzaG93L2hpZGUgcHJldmlld3MuXG4gICAqL1xuICBwcmV2aWV3Q29uZmlnOiBQcmV2aWV3Q29uZmlnIHwgdW5kZWZpbmVkO1xuICAvKipcbiAgICogT2JqZWN0IG9mIHR5cGUgYFNsaWRlQ29uZmlnYCB0byBpbml0IHNpZGUgcHJldmlld3MgYW5kIGBpbmZpbml0ZSBzbGlkaW5nYC5cbiAgICovXG4gIHNsaWRlQ29uZmlnOiBTbGlkZUNvbmZpZyB8IHVuZGVmaW5lZDtcbiAgLyoqXG4gICAqIE9iamVjdCBvZiB0eXBlIGBBY2Nlc3NpYmlsaXR5Q29uZmlnYCB0byBpbml0IGN1c3RvbSBhY2Nlc3NpYmlsaXR5IGZlYXR1cmVzLlxuICAgKiBGb3IgaW5zdGFuY2UsIGl0IGNvbnRhaW5zIHRpdGxlcywgYWx0IHRleHRzLCBhcmlhLWxhYmVscyBhbmQgc28gb24uXG4gICAqL1xuICBhY2Nlc3NpYmlsaXR5Q29uZmlnOiBBY2Nlc3NpYmlsaXR5Q29uZmlnID0gS1NfREVGQVVMVF9BQ0NFU1NJQklMSVRZX0NPTkZJRztcbiAgLyoqXG4gICAqIE9iamVjdCBvZiB0eXBlIGBLZXlib2FyZENvbmZpZ2AgdG8gYXNzaWduIGN1c3RvbSBrZXlzIHRvIEVTQywgUklHSFQgYW5kIExFRlQga2V5Ym9hcmQncyBhY3Rpb25zLlxuICAgKi9cbiAga2V5Ym9hcmRDb25maWc6IEtleWJvYXJkQ29uZmlnIHwgdW5kZWZpbmVkO1xuICAvKipcbiAgICogT2JqZWN0IG9mIHR5cGUgYFBsYWluR2FsbGVyeUNvbmZpZ2AgdG8gY29uZmlndXJlIHRoZSBwbGFpbiBnYWxsZXJ5LlxuICAgKi9cbiAgcGxhaW5HYWxsZXJ5Q29uZmlnOiBQbGFpbkdhbGxlcnlDb25maWcgfCB1bmRlZmluZWQ7XG5cbiAgLyoqXG4gICAqIEFycmF5IG9mIGBJbnRlcm5hbExpYkltYWdlYCByZXByZXNlbnRpbmcgdGhlIG1vZGVsIG9mIHRoaXMgbGlicmFyeSB3aXRoIGFsbCBpbWFnZXMsIHRodW1icyBhbmQgc28gb24uXG4gICAqL1xuICBpbWFnZXM6IEludGVybmFsTGliSW1hZ2VbXTtcbiAgLyoqXG4gICAqIGBJbWFnZWAgdGhhdCBpcyB2aXNpYmxlIHJpZ2h0IG5vdy5cbiAgICovXG4gIGN1cnJlbnRJbWFnZTogSW50ZXJuYWxMaWJJbWFnZTtcbiAgLyoqXG4gICAqIEJvb2xlYW4gdG8gb3BlbiB0aGUgbW9kYWwgZ2FsbGVyeS4gRmFsc2UgYnkgZGVmYXVsdC5cbiAgICovXG4gIHNob3dHYWxsZXJ5ID0gZmFsc2U7XG4gIC8qKlxuICAgKiBUT0RPIHdyaXRlIGRvY1xuICAgKi9cbiAgbGliQ29uZmlnOiBMaWJDb25maWcgfCB1bmRlZmluZWQ7XG5cbiAgcHJpdmF0ZSB1cGRhdGVJbWFnZXNTdWJzY3JpcHRpb246IFN1YnNjcmlwdGlvbiB8IHVuZGVmaW5lZDtcblxuICAvKipcbiAgICogSG9zdExpc3RlbmVyIHRvIGNhdGNoIGJyb3dzZXIncyBiYWNrIGJ1dHRvbiBhbmQgZGVzdHJveSB0aGUgZ2FsbGVyeS5cbiAgICogVGhpcyBwcmV2ZW50cyB3ZWlyZWQgYmVoYXZpb3VyIGFib3V0IHNjcm9sbGluZy5cbiAgICogQWRkZWQgdG8gZml4IHRoaXMgaXNzdWU6IGh0dHBzOi8vZ2l0aHViLmNvbS9Lczg5L2FuZ3VsYXItbW9kYWwtZ2FsbGVyeS9pc3N1ZXMvMTU5XG4gICAqL1xuICBASG9zdExpc3RlbmVyKCd3aW5kb3c6cG9wc3RhdGUnLCBbJyRldmVudCddKVxuICBvblBvcFN0YXRlKGU6IEV2ZW50KTogdm9pZCB7XG4gICAgdGhpcy5jbG9zZUdhbGxlcnkoKTtcbiAgfVxuXG4gIGNvbnN0cnVjdG9yKFxuICAgIEBJbmplY3QoRElBTE9HX0RBVEEpIHByaXZhdGUgZGlhbG9nQ29udGVudDogTW9kYWxHYWxsZXJ5Q29uZmlnLFxuICAgIHByaXZhdGUgbW9kYWxHYWxsZXJ5U2VydmljZTogTW9kYWxHYWxsZXJ5U2VydmljZSxcbiAgICBwcml2YXRlIGtleWJvYXJkU2VydmljZTogS2V5Ym9hcmRTZXJ2aWNlLFxuICAgIC8vIHRzbGludDpkaXNhYmxlLW5leHQtbGluZTpiYW4tdHlwZXNcbiAgICBASW5qZWN0KFBMQVRGT1JNX0lEKSBwcml2YXRlIHBsYXRmb3JtSWQ6IE9iamVjdCxcbiAgICBwcml2YXRlIGNoYW5nZURldGVjdG9yUmVmOiBDaGFuZ2VEZXRlY3RvclJlZixcbiAgICBwcml2YXRlIGlkVmFsaWRhdG9yU2VydmljZTogSWRWYWxpZGF0b3JTZXJ2aWNlLFxuICAgIHByaXZhdGUgY29uZmlnU2VydmljZTogQ29uZmlnU2VydmljZSxcbiAgICBwcml2YXRlIHNhbml0aXplcjogRG9tU2FuaXRpemVyXG4gICkge1xuICAgIHRoaXMuaWQgPSAodGhpcy5kaWFsb2dDb250ZW50IGFzIE1vZGFsR2FsbGVyeUNvbmZpZykuaWQ7XG4gICAgdGhpcy5pbWFnZXMgPSAodGhpcy5kaWFsb2dDb250ZW50IGFzIE1vZGFsR2FsbGVyeUNvbmZpZykuaW1hZ2VzIGFzIEludGVybmFsTGliSW1hZ2VbXTtcbiAgICB0aGlzLmN1cnJlbnRJbWFnZSA9ICh0aGlzLmRpYWxvZ0NvbnRlbnQgYXMgTW9kYWxHYWxsZXJ5Q29uZmlnKS5jdXJyZW50SW1hZ2UgYXMgSW50ZXJuYWxMaWJJbWFnZTtcbiAgICB0aGlzLmxpYkNvbmZpZyA9ICh0aGlzLmRpYWxvZ0NvbnRlbnQgYXMgTW9kYWxHYWxsZXJ5Q29uZmlnKS5saWJDb25maWc7XG4gICAgdGhpcy5jb25maWdTZXJ2aWNlLnNldENvbmZpZyh0aGlzLmlkLCB0aGlzLmxpYkNvbmZpZyk7XG5cbiAgICB0aGlzLnVwZGF0ZUltYWdlc1N1YnNjcmlwdGlvbiA9IHRoaXMubW9kYWxHYWxsZXJ5U2VydmljZS51cGRhdGVJbWFnZXMkLnN1YnNjcmliZSgoaW1hZ2VzOiBJbWFnZVtdKSA9PiB7XG4gICAgICB0aGlzLmltYWdlcyA9IGltYWdlcy5tYXAoKGltYWdlOiBJbWFnZSkgPT4ge1xuICAgICAgICBjb25zdCBuZXdJbWFnZTogSW50ZXJuYWxMaWJJbWFnZSA9IE9iamVjdC5hc3NpZ24oe30sIGltYWdlLCB7IHByZXZpb3VzbHlMb2FkZWQ6IGZhbHNlIH0pO1xuICAgICAgICByZXR1cm4gbmV3SW1hZ2U7XG4gICAgICB9KTtcbiAgICAgIHRoaXMuaW5pdEltYWdlcygpO1xuICAgICAgdGhpcy5pbWFnZXMuZm9yRWFjaCgoaW1hZ2U6IEludGVybmFsTGliSW1hZ2UpID0+IHtcbiAgICAgICAgaWYgKGltYWdlLmlkID09PSB0aGlzLmN1cnJlbnRJbWFnZS5pZCkge1xuICAgICAgICAgIHRoaXMuY3VycmVudEltYWdlID0gaW1hZ2U7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgICAgdGhpcy5jaGFuZ2VEZXRlY3RvclJlZi5tYXJrRm9yQ2hlY2soKTtcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBNZXRob2QgwrRuZ09uSW5pdMK0IHRvIGluaXQgaW1hZ2VzIGNhbGxpbmcgYGluaXRJbWFnZXMoKWAuXG4gICAqIFRoaXMgaXMgYW4gQW5ndWxhcidzIGxpZmVjeWNsZSBob29rLCBzbyBpdHMgY2FsbGVkIGF1dG9tYXRpY2FsbHkgYnkgQW5ndWxhciBpdHNlbGYuXG4gICAqIEluIHBhcnRpY3VsYXIsIGl0J3MgY2FsbGVkIG9ubHkgb25lIHRpbWUhISFcbiAgICovXG4gIG5nT25Jbml0KCk6IHZvaWQge1xuICAgIHRoaXMuaWRWYWxpZGF0b3JTZXJ2aWNlLmNoZWNrQW5kQWRkKHRoaXMuaWQpO1xuXG4gICAgLy8gaWQgaXMgYSBtYW5kYXRvcnkgaW5wdXQgYW5kIG11c3QgYSBudW1iZXIgPiAwXG4gICAgaWYgKCghdGhpcy5pZCAmJiB0aGlzLmlkICE9PSAwKSB8fCB0aGlzLmlkIDwgMCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICBgJ1tpZF09XCJhIG51bWJlciA+PSAwXCInIGlzIGEgbWFuZGF0b3J5IGlucHV0IGluIGFuZ3VsYXItbW9kYWwtZ2FsbGVyeS5gICtcbiAgICAgICAgICBgSWYgeW91IGFyZSB1c2luZyBtdWx0aXBsZSBpbnN0YW5jZXMgb2YgdGhpcyBsaWJyYXJ5LCBwbGVhc2UgYmUgc3VyZSB0byB1c2UgZGlmZmVyZW50IGlkc2BcbiAgICAgICk7XG4gICAgfVxuXG4gICAgY29uc3QgbGliQ29uZmlnOiBMaWJDb25maWcgfCB1bmRlZmluZWQgPSB0aGlzLmNvbmZpZ1NlcnZpY2UuZ2V0Q29uZmlnKHRoaXMuaWQpO1xuICAgIGlmICghbGliQ29uZmlnIHx8ICFsaWJDb25maWcuZG90c0NvbmZpZykge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnRlcm5hbCBsaWJyYXJ5IGVycm9yIC0gbGliQ29uZmlnIGFuZCBkb3RzQ29uZmlnIG11c3QgYmUgZGVmaW5lZCcpO1xuICAgIH1cblxuICAgIHRoaXMuZG90c0NvbmZpZyA9IGxpYkNvbmZpZy5kb3RzQ29uZmlnO1xuXG4gICAgLy8gY2FsbCBpbml0SW1hZ2VzIHRvIGluaXQgaW1hZ2VzIGFuZCB0byBlbWl0IGBoYXNEYXRhYCBldmVudFxuICAgIHRoaXMuaW5pdEltYWdlcygpO1xuICAgIHRoaXMuc2hvd01vZGFsR2FsbGVyeSgpO1xuICB9XG5cbiAgLyoqXG4gICAqIE1ldGhvZCBjYWxsZWQgYnkgY3VzdG9tIHVwcGVyIGJ1dHRvbnMuXG4gICAqIEBwYXJhbSBldmVudCBCdXR0b25FdmVudCBwYXlsb2FkXG4gICAqL1xuICBvbkN1c3RvbUVtaXQoZXZlbnQ6IEJ1dHRvbkV2ZW50KTogdm9pZCB7XG4gICAgY29uc3QgZXZlbnRUb0VtaXQ6IEJ1dHRvbkV2ZW50ID0gdGhpcy5nZXRCdXR0b25FdmVudFRvRW1pdChldmVudCk7XG4gICAgdGhpcy5tb2RhbEdhbGxlcnlTZXJ2aWNlLmVtaXRCdXR0b25CZWZvcmVIb29rKGV2ZW50VG9FbWl0KTtcbiAgICB0aGlzLm1vZGFsR2FsbGVyeVNlcnZpY2UuZW1pdEJ1dHRvbkFmdGVySG9vayhldmVudFRvRW1pdCk7XG4gIH1cblxuICAvKipcbiAgICogTWV0aG9kIGNhbGxlZCBieSB0aGUgZnVsbC1zY3JlZW4gdXBwZXIgYnV0dG9uLlxuICAgKiBAcGFyYW0gQnV0dG9uRXZlbnQgZXZlbnQgcGF5bG9hZFxuICAgKi9cbiAgb25GdWxsU2NyZWVuKGV2ZW50OiBCdXR0b25FdmVudCk6IHZvaWQge1xuICAgIGNvbnN0IGV2ZW50VG9FbWl0OiBCdXR0b25FdmVudCA9IHRoaXMuZ2V0QnV0dG9uRXZlbnRUb0VtaXQoZXZlbnQpO1xuICAgIHRoaXMubW9kYWxHYWxsZXJ5U2VydmljZS5lbWl0QnV0dG9uQmVmb3JlSG9vayhldmVudFRvRW1pdCk7XG5cbiAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6bm8tYW55XG4gICAgY29uc3QgZG9jOiBhbnkgPSBkb2N1bWVudCBhcyBhbnk7XG4gICAgLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lOm5vLWFueVxuICAgIGNvbnN0IGRvY0VsOiBhbnkgPSBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQgYXMgYW55O1xuXG4gICAgY29uc3QgZnVsbHNjcmVlbkRpc2FibGVkOiBib29sZWFuID0gIWRvYy5mdWxsc2NyZWVuRWxlbWVudCAmJiAhZG9jLndlYmtpdEZ1bGxzY3JlZW5FbGVtZW50ICYmICFkb2MubW96RnVsbFNjcmVlbkVsZW1lbnQgJiYgIWRvYy5tc0Z1bGxzY3JlZW5FbGVtZW50O1xuXG4gICAgaWYgKGZ1bGxzY3JlZW5EaXNhYmxlZCkge1xuICAgICAgaWYgKGRvY0VsLnJlcXVlc3RGdWxsc2NyZWVuKSB7XG4gICAgICAgIGRvY0VsLnJlcXVlc3RGdWxsc2NyZWVuKCk7XG4gICAgICB9IGVsc2UgaWYgKGRvY0VsLndlYmtpdFJlcXVlc3RGdWxsc2NyZWVuKSB7XG4gICAgICAgIGRvY0VsLndlYmtpdFJlcXVlc3RGdWxsc2NyZWVuKCk7XG4gICAgICB9IGVsc2UgaWYgKGRvY0VsLm1velJlcXVlc3RGdWxsU2NyZWVuKSB7XG4gICAgICAgIGRvY0VsLm1velJlcXVlc3RGdWxsU2NyZWVuKCk7XG4gICAgICB9IGVsc2UgaWYgKGRvY0VsLm1zUmVxdWVzdEZ1bGxzY3JlZW4pIHtcbiAgICAgICAgZG9jRWwubXNSZXF1ZXN0RnVsbHNjcmVlbigpO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICBpZiAoZG9jLmV4aXRGdWxsc2NyZWVuKSB7XG4gICAgICAgIGRvYy5leGl0RnVsbHNjcmVlbigpO1xuICAgICAgfSBlbHNlIGlmIChkb2MubXNFeGl0RnVsbHNjcmVlbikge1xuICAgICAgICBkb2MubXNFeGl0RnVsbHNjcmVlbigpO1xuICAgICAgfSBlbHNlIGlmIChkb2MubW96Q2FuY2VsRnVsbFNjcmVlbikge1xuICAgICAgICBkb2MubW96Q2FuY2VsRnVsbFNjcmVlbigpO1xuICAgICAgfSBlbHNlIGlmIChkb2Mud2Via2l0RXhpdEZ1bGxzY3JlZW4pIHtcbiAgICAgICAgZG9jLndlYmtpdEV4aXRGdWxsc2NyZWVuKCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgdGhpcy5tb2RhbEdhbGxlcnlTZXJ2aWNlLmVtaXRCdXR0b25BZnRlckhvb2soZXZlbnRUb0VtaXQpO1xuICB9XG5cbiAgLyoqXG4gICAqIE1ldGhvZCBjYWxsZWQgYnkgdGhlIGRlbGV0ZSB1cHBlciBidXR0b24uXG4gICAqIEBwYXJhbSBCdXR0b25FdmVudCBldmVudCBwYXlsb2FkXG4gICAqL1xuICBvbkRlbGV0ZShldmVudDogQnV0dG9uRXZlbnQpOiB2b2lkIHtcbiAgICBjb25zdCBldmVudFRvRW1pdDogQnV0dG9uRXZlbnQgPSB0aGlzLmdldEJ1dHRvbkV2ZW50VG9FbWl0KGV2ZW50KTtcbiAgICB0aGlzLm1vZGFsR2FsbGVyeVNlcnZpY2UuZW1pdEJ1dHRvbkJlZm9yZUhvb2soZXZlbnRUb0VtaXQpO1xuXG4gICAgaWYgKHRoaXMuaW1hZ2VzLmxlbmd0aCA9PT0gMSkge1xuICAgICAgdGhpcy5jbG9zZUdhbGxlcnkoKTtcbiAgICB9XG5cbiAgICBpZiAoIXRoaXMuY3VycmVudEltYWdlQ29tcG9uZW50KSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ2N1cnJlbnRJbWFnZUNvbXBvbmVudCBtdXN0IGJlIGRlZmluZWQnKTtcbiAgICB9XG5cbiAgICBjb25zdCBpbWFnZUluZGV4VG9EZWxldGU6IG51bWJlciA9IHRoaXMuY3VycmVudEltYWdlQ29tcG9uZW50LmdldEluZGV4VG9EZWxldGUoZXZlbnQuaW1hZ2UgYXMgSW50ZXJuYWxMaWJJbWFnZSk7XG4gICAgaWYgKGltYWdlSW5kZXhUb0RlbGV0ZSA9PT0gdGhpcy5pbWFnZXMubGVuZ3RoIC0gMSkge1xuICAgICAgLy8gbGFzdCBpbWFnZVxuICAgICAgdGhpcy5jdXJyZW50SW1hZ2VDb21wb25lbnQucHJldkltYWdlKCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuY3VycmVudEltYWdlQ29tcG9uZW50Lm5leHRJbWFnZSgpO1xuICAgIH1cblxuICAgIHRoaXMubW9kYWxHYWxsZXJ5U2VydmljZS5lbWl0QnV0dG9uQWZ0ZXJIb29rKGV2ZW50VG9FbWl0KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBNZXRob2QgY2FsbGVkIGJ5IHRoZSBuYXZpZ2F0ZSB1cHBlciBidXR0b24uXG4gICAqIEBwYXJhbSBCdXR0b25FdmVudCBldmVudCBwYXlsb2FkXG4gICAqL1xuICBvbk5hdmlnYXRlKGV2ZW50OiBCdXR0b25FdmVudCk6IHZvaWQge1xuICAgIGNvbnN0IGV2ZW50VG9FbWl0OiBCdXR0b25FdmVudCA9IHRoaXMuZ2V0QnV0dG9uRXZlbnRUb0VtaXQoZXZlbnQpO1xuICAgIHRoaXMubW9kYWxHYWxsZXJ5U2VydmljZS5lbWl0QnV0dG9uQmVmb3JlSG9vayhldmVudFRvRW1pdCk7XG4gICAgLy8gVG8gc3VwcG9ydCBTU1JcbiAgICBpZiAoaXNQbGF0Zm9ybUJyb3dzZXIodGhpcy5wbGF0Zm9ybUlkKSkge1xuICAgICAgaWYgKGV2ZW50VG9FbWl0LmltYWdlICYmIGV2ZW50VG9FbWl0LmltYWdlLm1vZGFsLmV4dFVybCkge1xuICAgICAgICAvLyB3aGVyZSBJIHNob3VsZCBvcGVuIHRoaXMgbGluaz8gVGhlIGN1cnJlbnQgdGFiIG9yIGFub3RoZXIgb25lP1xuICAgICAgICBpZiAoZXZlbnRUb0VtaXQuYnV0dG9uICYmIGV2ZW50VG9FbWl0LmJ1dHRvbi5leHRVcmxJbk5ld1RhYikge1xuICAgICAgICAgIC8vIGluIHRoaXMgY2FzZSBJIHNob3VsZCB1c2UgdGFyZ2V0IF9ibGFuayB0byBvcGVuIHRoZSB1cmwgaW4gYSBuZXcgdGFiLCBob3dldmVyIHRoZXNlIGlzIGEgc2VjdXJpdHkgaXNzdWUuXG4gICAgICAgICAgLy8gUHJldmVudCBSZXZlcnNlIFRhYm5hYmJpbmcncyBhdHRhY2tzIChodHRwczovL3d3dy5vd2FzcC5vcmcvaW5kZXgucGhwL1JldmVyc2VfVGFibmFiYmluZylcbiAgICAgICAgICAvLyBTb21lIHJlc291cmNlczpcbiAgICAgICAgICAvLyAtIGh0dHBzOi8vd3d3Lm93YXNwLm9yZy9pbmRleC5waHAvSFRNTDVfU2VjdXJpdHlfQ2hlYXRfU2hlZXQjVGFibmFiYmluZ1xuICAgICAgICAgIC8vIC0gaHR0cHM6Ly9tZWRpdW0uY29tL0BqaXRiaXQvdGFyZ2V0LWJsYW5rLXRoZS1tb3N0LXVuZGVyZXN0aW1hdGVkLXZ1bG5lcmFiaWxpdHktZXZlci05NmUzMjgzMDFmNGNcbiAgICAgICAgICAvLyAtIGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0FQSS9XaW5kb3cvb3BlblxuICAgICAgICAgIGNvbnN0IG5ld1dpbmRvdzogV2luZG93IHwgbnVsbCA9IHdpbmRvdy5vcGVuKGV2ZW50VG9FbWl0LmltYWdlLm1vZGFsLmV4dFVybCwgJ25vb3BlbmVyLG5vcmVmZXJyZXIsJyk7XG4gICAgICAgICAgLy8gaXQgcmV0dXJucyBudWxsIGlmIHRoZSBjYWxsIGZhaWxlZCwgc28gSSBoYXZlIHRvIGRvIHRoaXMgY2hlY2tcbiAgICAgICAgICBpZiAobmV3V2luZG93KSB7XG4gICAgICAgICAgICBuZXdXaW5kb3cub3BlbmVyID0gbnVsbDsgLy8gcmVxdWlyZWQgdG8gcHJldmVudCBzZWN1cml0eSBpc3N1ZXNcbiAgICAgICAgICAgIC8vIGVtaXQgb25seSBpbiBjYXNlIG9mIHN1Y2Nlc3NcbiAgICAgICAgICAgIHRoaXMubW9kYWxHYWxsZXJ5U2VydmljZS5lbWl0QnV0dG9uQWZ0ZXJIb29rKGV2ZW50VG9FbWl0KTtcbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgd2luZG93LmxvY2F0aW9uLmhyZWYgPSBldmVudFRvRW1pdC5pbWFnZS5tb2RhbC5leHRVcmw7XG4gICAgICAgICAgLy8gZW1pdCBvbmx5IGluIGNhc2Ugb2Ygc3VjY2Vzc1xuICAgICAgICAgIHRoaXMubW9kYWxHYWxsZXJ5U2VydmljZS5lbWl0QnV0dG9uQWZ0ZXJIb29rKGV2ZW50VG9FbWl0KTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBNZXRob2QgY2FsbGVkIGJ5IHRoZSBkb3dubG9hZCB1cHBlciBidXR0b24uXG4gICAqIEBwYXJhbSBCdXR0b25FdmVudCBldmVudCBwYXlsb2FkXG4gICAqL1xuICBvbkRvd25sb2FkKGV2ZW50OiBCdXR0b25FdmVudCk6IHZvaWQge1xuICAgIGNvbnN0IGV2ZW50VG9FbWl0OiBCdXR0b25FdmVudCA9IHRoaXMuZ2V0QnV0dG9uRXZlbnRUb0VtaXQoZXZlbnQpO1xuICAgIHRoaXMubW9kYWxHYWxsZXJ5U2VydmljZS5lbWl0QnV0dG9uQmVmb3JlSG9vayhldmVudFRvRW1pdCk7XG4gICAgdGhpcy5kb3dubG9hZEltYWdlKCk7XG4gICAgdGhpcy5tb2RhbEdhbGxlcnlTZXJ2aWNlLmVtaXRCdXR0b25BZnRlckhvb2soZXZlbnRUb0VtaXQpO1xuICB9XG5cbiAgLyoqXG4gICAqIE1ldGhvZCBjYWxsZWQgYnkgdGhlIGNsb3NlIHVwcGVyIGJ1dHRvbi5cbiAgICogQHBhcmFtIEJ1dHRvbkV2ZW50IGV2ZW50IHBheWxvYWRcbiAgICogQHBhcmFtIEFjdGlvbiBhY3Rpb24gdGhhdCB0cmlnZ2VyZWQgdGhlIGNsb3NlIG1ldGhvZC4gYEFjdGlvbi5OT1JNQUxgIGJ5IGRlZmF1bHRcbiAgICovXG4gIG9uQ2xvc2VHYWxsZXJ5KGV2ZW50OiBCdXR0b25FdmVudCwgYWN0aW9uOiBBY3Rpb24gPSBBY3Rpb24uTk9STUFMKTogdm9pZCB7XG4gICAgY29uc3QgZXZlbnRUb0VtaXQ6IEJ1dHRvbkV2ZW50ID0gdGhpcy5nZXRCdXR0b25FdmVudFRvRW1pdChldmVudCk7XG4gICAgdGhpcy5tb2RhbEdhbGxlcnlTZXJ2aWNlLmVtaXRCdXR0b25CZWZvcmVIb29rKGV2ZW50VG9FbWl0KTtcbiAgICB0aGlzLmNsb3NlR2FsbGVyeShhY3Rpb24sIGZhbHNlKTtcbiAgICB0aGlzLm1vZGFsR2FsbGVyeVNlcnZpY2UuZW1pdEJ1dHRvbkFmdGVySG9vayhldmVudFRvRW1pdCk7XG4gIH1cblxuICAvKipcbiAgICogTWV0aG9kIHRvIGNsb3NlIHRoZSBtb2RhbCBnYWxsZXJ5IHNwZWNpZnlpbmcgdGhlIGFjdGlvbi5cbiAgICogSXQgYWxzbyByZXNldCB0aGUgYGtleWJvYXJkU2VydmljZWAgdG8gcHJldmVudCBtdWx0aXBsZSBsaXN0ZW5lcnMuXG4gICAqIEBwYXJhbSBBY3Rpb24gYWN0aW9uIHR5cGUuIGBBY3Rpb24uTk9STUFMYCBieSBkZWZhdWx0XG4gICAqIEBwYXJhbSBib29sZWFuIGlzQ2FsbGVkQnlTZXJ2aWNlIGlzIHRydWUgaWYgY2FsbGVkIGJ5IGdhbGxlcnkuc2VydmljZSwgb3RoZXJ3aXNlIGZhbHNlXG4gICAqL1xuICBjbG9zZUdhbGxlcnkoYWN0aW9uOiBBY3Rpb24gPSBBY3Rpb24uTk9STUFMLCBjbGlja091dHNpZGU6IGJvb2xlYW4gPSBmYWxzZSwgaXNDYWxsZWRCeVNlcnZpY2U6IGJvb2xlYW4gPSBmYWxzZSk6IHZvaWQge1xuICAgIGNvbnN0IGxpYkNvbmZpZzogTGliQ29uZmlnIHwgdW5kZWZpbmVkID0gdGhpcy5jb25maWdTZXJ2aWNlLmdldENvbmZpZyh0aGlzLmlkKTtcbiAgICBpZiAoIWxpYkNvbmZpZykge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnRlcm5hbCBsaWJyYXJ5IGVycm9yIC0gbGliQ29uZmlnIG11c3QgYmUgZGVmaW5lZCcpO1xuICAgIH1cblxuICAgIHRoaXMubW9kYWxHYWxsZXJ5U2VydmljZS5lbWl0Q2xvc2UobmV3IEltYWdlTW9kYWxFdmVudCh0aGlzLmlkLCBhY3Rpb24sIHRydWUpKTtcbiAgICB0aGlzLmtleWJvYXJkU2VydmljZS5yZXNldChsaWJDb25maWcpO1xuICAgIHRoaXMubW9kYWxHYWxsZXJ5U2VydmljZS5jbG9zZSh0aGlzLmlkLCBjbGlja091dHNpZGUpO1xuXG4gICAgLy8gc2hvd3Mgc2Nyb2xsYmFyXG4gICAgZG9jdW1lbnQuYm9keS5zdHlsZS5vdmVyZmxvdyA9ICd2aXNpYmxlJztcblxuICAgIGlmIChpc0NhbGxlZEJ5U2VydmljZSkge1xuICAgICAgLy8gdGhlIGZvbGxvd2luZyBpcyByZXF1aXJlZCwgb3RoZXJ3aXNlIHRoZSB2aWV3IHdpbGwgbm90IGJlIHVwZGF0ZWRcbiAgICAgIC8vIHRoaXMgaGFwcGVucyBvbmx5IGlmIGNhbGxlZCBieSBnYWxsZXJ5LnNlcnZpY2VcbiAgICAgIHRoaXMuY2hhbmdlRGV0ZWN0b3JSZWYubWFya0ZvckNoZWNrKCk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIE1ldGhvZCB0byBzaG93IHRoZSBtb2RhbCBnYWxsZXJ5IGRpc3BsYXlpbmcgdGhlIGltYWdlIHdpdGhcbiAgICogdGhlIGluZGV4IHNwZWNpZmllZCBhcyBpbnB1dCBwYXJhbWV0ZXIuXG4gICAqIEl0IHdpbGwgYWxzbyByZWdpc3RlciBhIG5ldyBga2V5Ym9hcmRTZXJ2aWNlYCB0byBjYXRjaCBrZXlib2FyZCdzIGV2ZW50cyB0byBkb3dubG9hZCB0aGUgY3VycmVudFxuICAgKiBpbWFnZSB3aXRoIGtleWJvYXJkJ3Mgc2hvcnRjdXRzLiBUaGlzIHNlcnZpY2UsIHdpbGwgYmUgcmVtb3ZlZCBlaXRoZXIgd2hlbiBtb2RhbCBnYWxsZXJ5IGNvbXBvbmVudFxuICAgKiB3aWxsIGJlIGRlc3Ryb3llZCBvciB3aGVuIHRoZSBnYWxsZXJ5IGlzIGNsb3NlZCBpbnZva2luZyB0aGUgYGNsb3NlR2FsbGVyeWAgbWV0aG9kLlxuICAgKiBAcGFyYW0gbnVtYmVyIGluZGV4IG9mIHRoZSBpbWFnZSB0byBzaG93XG4gICAqL1xuICBzaG93TW9kYWxHYWxsZXJ5KCk6IHZvaWQge1xuICAgIC8vIGhpZGVzIHNjcm9sbGJhclxuICAgIGRvY3VtZW50LmJvZHkuc3R5bGUub3ZlcmZsb3cgPSAnaGlkZGVuJztcblxuICAgIGlmICghdGhpcy5pZCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnRlcm5hbCBsaWJyYXJ5IGVycm9yIC0gaWQgbXVzdCBiZSBkZWZpbmVkJyk7XG4gICAgfVxuICAgIGNvbnN0IGxpYkNvbmZpZzogTGliQ29uZmlnIHwgdW5kZWZpbmVkID0gdGhpcy5jb25maWdTZXJ2aWNlLmdldENvbmZpZyh0aGlzLmlkKTtcbiAgICBpZiAoIWxpYkNvbmZpZykge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnRlcm5hbCBsaWJyYXJ5IGVycm9yIC0gbGliQ29uZmlnIG11c3QgYmUgZGVmaW5lZCcpO1xuICAgIH1cblxuICAgIHRoaXMua2V5Ym9hcmRTZXJ2aWNlLmluaXQobGliQ29uZmlnKS50aGVuKCgpID0+IHtcbiAgICAgIHRoaXMua2V5Ym9hcmRTZXJ2aWNlLmFkZCgoZXZlbnQ6IEtleWJvYXJkRXZlbnQsIGNvbWJvOiBzdHJpbmcpID0+IHtcbiAgICAgICAgaWYgKGV2ZW50LnByZXZlbnREZWZhdWx0KSB7XG4gICAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAvLyBpbnRlcm5ldCBleHBsb3JlclxuICAgICAgICAgIGV2ZW50LnJldHVyblZhbHVlID0gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5kb3dubG9hZEltYWdlKCk7XG4gICAgICB9LCBsaWJDb25maWcpO1xuXG4gICAgICBjb25zdCBjdXJyZW50SW5kZXg6IG51bWJlciA9IHRoaXMuaW1hZ2VzLmluZGV4T2YodGhpcy5jdXJyZW50SW1hZ2UpO1xuICAgICAgLy8gZW1pdCBhIG5ldyBJbWFnZU1vZGFsRXZlbnQgd2l0aCB0aGUgaW5kZXggb2YgdGhlIGN1cnJlbnQgaW1hZ2VcbiAgICAgIHRoaXMubW9kYWxHYWxsZXJ5U2VydmljZS5lbWl0U2hvdyhuZXcgSW1hZ2VNb2RhbEV2ZW50KHRoaXMuaWQsIEFjdGlvbi5MT0FELCBjdXJyZW50SW5kZXggKyAxKSk7XG4gICAgICB0aGlzLmNoYW5nZURldGVjdG9yUmVmLm1hcmtGb3JDaGVjaygpO1xuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIE1ldGhvZCBjYWxsZWQgd2hlbiB0aGUgaW1hZ2UgY2hhbmdlcyBhbmQgdXNlZCB0byB1cGRhdGUgdGhlIGBjdXJyZW50SW1hZ2VgIG9iamVjdC5cbiAgICogQHBhcmFtIEltYWdlTW9kYWxFdmVudCBldmVudCBwYXlsb2FkXG4gICAqL1xuICBvbkNoYW5nZUN1cnJlbnRJbWFnZShldmVudDogSW1hZ2VNb2RhbEV2ZW50KTogdm9pZCB7XG4gICAgY29uc3QgbmV3SW5kZXg6IG51bWJlciA9IGV2ZW50LnJlc3VsdCBhcyBudW1iZXI7XG4gICAgaWYgKG5ld0luZGV4IDwgMCB8fCBuZXdJbmRleCA+PSB0aGlzLmltYWdlcy5sZW5ndGgpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB0aGlzLmN1cnJlbnRJbWFnZSA9IHRoaXMuaW1hZ2VzW25ld0luZGV4XTtcblxuICAgIC8vIGVtaXQgZmlyc3QvbGFzdCBldmVudCBiYXNlZCBvbiBuZXdJbmRleCB2YWx1ZVxuICAgIHRoaXMuZW1pdEJvdW5kYXJ5RXZlbnQoZXZlbnQuYWN0aW9uLCBuZXdJbmRleCk7XG5cbiAgICAvLyBlbWl0IGN1cnJlbnQgdmlzaWJsZSBpbWFnZSBpbmRleFxuICAgIHRoaXMubW9kYWxHYWxsZXJ5U2VydmljZS5lbWl0U2hvdyhuZXcgSW1hZ2VNb2RhbEV2ZW50KHRoaXMuaWQsIGV2ZW50LmFjdGlvbiwgbmV3SW5kZXggKyAxKSk7XG4gIH1cblxuICAvKipcbiAgICogTWV0aG9kIGNhbGxlZCB3aGVuIHlvdSBjbGljayAnb3V0c2lkZScgKGkuZS4gb24gdGhlIHNlbWktdHJhbnNwYXJlbnQgYmFja2dyb3VuZClcbiAgICogdG8gY2xvc2UgdGhlIG1vZGFsIGdhbGxlcnkgaWYgYGVuYWJsZUNsb3NlT3V0c2lkZWAgaXMgdHJ1ZS5cbiAgICogQHBhcmFtIGJvb2xlYW4gZXZlbnQgcGF5bG9hZC4gVHJ1ZSB0byBjbG9zZSB0aGUgbW9kYWwgZ2FsbGVyeSwgZmFsc2Ugb3RoZXJ3aXNlXG4gICAqL1xuICBvbkNsaWNrT3V0c2lkZShldmVudDogYm9vbGVhbik6IHZvaWQge1xuICAgIGlmIChldmVudCAmJiB0aGlzLmVuYWJsZUNsb3NlT3V0c2lkZSkge1xuICAgICAgdGhpcy5jbG9zZUdhbGxlcnkoQWN0aW9uLkNMSUNLLCB0cnVlKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogTWV0aG9kIGNhbGxlZCB3aGVuIGFuIGltYWdlIGlzIGxvYWRlZCBhbmQgdGhlIGxvYWRpbmcgc3Bpbm5lciBoYXMgZ29uZS5cbiAgICogSXQgc2V0cyB0aGUgcHJldmlvdXNseUxvYWRlZCBmbGFnIGluc2lkZSB0aGUgSW1hZ2UgdG8gaGlkZSBsb2FkaW5nIHNwaW5uZXIgd2hlbiBkaXNwbGF5ZWQgYWdhaW4uXG4gICAqIEBwYXJhbSBJbWFnZUxvYWRFdmVudCBldmVudCBwYXlsb2FkXG4gICAqL1xuICBvbkltYWdlTG9hZChldmVudDogSW1hZ2VMb2FkRXZlbnQpOiB2b2lkIHtcbiAgICAvLyBzZXRzIGFzIHByZXZpb3VzbHkgbG9hZGVkIHRoZSBpbWFnZSB3aXRoIGluZGV4IHNwZWNpZmllZCBieSBgZXZlbnQuc3RhdHVzYFxuICAgIHRoaXMuaW1hZ2VzID0gdGhpcy5pbWFnZXMubWFwKChpbWc6IEludGVybmFsTGliSW1hZ2UpID0+IHtcbiAgICAgIGlmIChpbWcgJiYgaW1nLmlkID09PSBldmVudC5pZCkge1xuICAgICAgICByZXR1cm4gT2JqZWN0LmFzc2lnbih7fSwgaW1nLCB7IHByZXZpb3VzbHlMb2FkZWQ6IGV2ZW50LnN0YXR1cyB9KTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBpbWc7XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogTWV0aG9kIGNhbGxlZCB3aGVuIGEgZG90IGlzIGNsaWNrZWQgYW5kIHVzZWQgdG8gdXBkYXRlIHRoZSBjdXJyZW50IGltYWdlLlxuICAgKiBAcGFyYW0gbnVtYmVyIGluZGV4IG9mIHRoZSBjbGlja2VkIGRvdFxuICAgKi9cbiAgb25DbGlja0RvdChpbmRleDogbnVtYmVyKTogdm9pZCB7XG4gICAgdGhpcy5jdXJyZW50SW1hZ2UgPSB0aGlzLmltYWdlc1tpbmRleF07XG4gIH1cblxuICAvKipcbiAgICogTWV0aG9kIGNhbGxlZCB3aGVuIGFuIGltYWdlIHByZXZpZXcgaXMgY2xpY2tlZCBhbmQgdXNlZCB0byB1cGRhdGUgdGhlIGN1cnJlbnQgaW1hZ2UuXG4gICAqIEBwYXJhbSBJbWFnZSBwcmV2aWV3IGltYWdlXG4gICAqL1xuICBvbkNsaWNrUHJldmlldyhldmVudDogSW1hZ2VNb2RhbEV2ZW50KTogdm9pZCB7XG4gICAgdGhpcy5vbkNoYW5nZUN1cnJlbnRJbWFnZShldmVudCk7XG4gIH1cblxuICAvKipcbiAgICogTWV0aG9kIHRvIGRvd25sb2FkIHRoZSBjdXJyZW50IGltYWdlLCBvbmx5IGlmIGBkb3dubG9hZGFibGVgIGlzIHRydWUuXG4gICAqIEl0IGNvbnRhaW5zIGFsc28gYSBsb2dpYyB0byBlbmFibGUgZG93bmxvYWRpbmcgZmVhdHVyZXMgYWxzbyBmb3IgSUUxMS5cbiAgICovXG4gIGRvd25sb2FkSW1hZ2UoKTogdm9pZCB7XG4gICAgaWYgKCF0aGlzLmlkKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludGVybmFsIGxpYnJhcnkgZXJyb3IgLSBpZCBtdXN0IGJlIGRlZmluZWQnKTtcbiAgICB9XG4gICAgY29uc3QgbGliQ29uZmlnOiBMaWJDb25maWcgfCB1bmRlZmluZWQgPSB0aGlzLmNvbmZpZ1NlcnZpY2UuZ2V0Q29uZmlnKHRoaXMuaWQpO1xuICAgIGlmICghbGliQ29uZmlnKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludGVybmFsIGxpYnJhcnkgZXJyb3IgLSBsaWJDb25maWcgbXVzdCBiZSBkZWZpbmVkJyk7XG4gICAgfVxuXG4gICAgY29uc3QgY3VycmVudEltYWdlQ29uZmlnOiBDdXJyZW50SW1hZ2VDb25maWcgfCB1bmRlZmluZWQgPSBsaWJDb25maWcuY3VycmVudEltYWdlQ29uZmlnO1xuICAgIGlmIChjdXJyZW50SW1hZ2VDb25maWcgJiYgIWN1cnJlbnRJbWFnZUNvbmZpZy5kb3dubG9hZGFibGUpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgLy8gSWYgSUUxMSBvciBNaWNyb3NvZnQgRWRnZSB1c2UgbXNTYXZlQmxvYiguLi4pXG4gICAgaWYgKHRoaXMuaXNJRW9yRWRnZSgpKSB7XG4gICAgICAvLyBJIGNhbm5vdCB1c2UgZmV0Y2ggQVBJIGJlY2F1c2UgSUUxMSBkb2Vzbid0IHN1cHBvcnQgaXQsXG4gICAgICAvLyBzbyBJIGhhdmUgdG8gc3dpdGNoIHRvIFhNTEh0dHBSZXF1ZXN0XG4gICAgICB0aGlzLmRvd25sb2FkSW1hZ2VPbmx5SUVvckVkZ2UoKTtcbiAgICB9IGVsc2Uge1xuICAgICAgLy8gZm9yIGFsbCBvdGhlciBicm93c2Vyc1xuICAgICAgdGhpcy5kb3dubG9hZEltYWdlQWxsQnJvd3NlcnMoKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogTWV0aG9kIHRvIGNsZWFudXAgcmVzb3VyY2VzLiBJbiBmYWN0LCB0aGlzIHdpbGwgcmVzZXQga2V5Ym9hcmQncyBzZXJ2aWNlLlxuICAgKiBUaGlzIGlzIGFuIEFuZ3VsYXIncyBsaWZlY3ljbGUgaG9vayB0aGF0IGlzIGNhbGxlZCB3aGVuIHRoaXMgY29tcG9uZW50IGlzIGRlc3Ryb3llZC5cbiAgICovXG4gIG5nT25EZXN0cm95KCk6IHZvaWQge1xuICAgIGlmICh0aGlzLmtleWJvYXJkU2VydmljZSkge1xuICAgICAgY29uc3QgbGliQ29uZmlnOiBMaWJDb25maWcgfCB1bmRlZmluZWQgPSB0aGlzLmNvbmZpZ1NlcnZpY2UuZ2V0Q29uZmlnKHRoaXMuaWQpO1xuICAgICAgaWYgKHRoaXMuaWQgJiYgbGliQ29uZmlnKSB7XG4gICAgICAgIHRoaXMua2V5Ym9hcmRTZXJ2aWNlLnJlc2V0KGxpYkNvbmZpZyk7XG4gICAgICB9XG4gICAgfVxuICAgIGlmICh0aGlzLnVwZGF0ZUltYWdlc1N1YnNjcmlwdGlvbikge1xuICAgICAgdGhpcy51cGRhdGVJbWFnZXNTdWJzY3JpcHRpb24udW5zdWJzY3JpYmUoKTtcbiAgICB9XG4gICAgdGhpcy5pZFZhbGlkYXRvclNlcnZpY2UucmVtb3ZlKHRoaXMuaWQpO1xuICB9XG5cbiAgLyoqXG4gICAqIE1ldGhvZCB0byBjb252ZXJ0IGEgYmFzZTY0IHRvIGEgQmxvYlxuICAgKiBAcGFyYW0gYmFzZTY0RGF0YSBzdHJpbmcgd2l0aCBiYXNlNjQgZGF0YVxuICAgKiBAcGFyYW0gY29udGVudFR5cGUgc3RyaW5nIHdpdGggdGhlIE1JTUUgdHlwZVxuICAgKi9cbiAgcHJpdmF0ZSBiYXNlNjR0b0Jsb2IoYmFzZTY0RGF0YTogc3RyaW5nLCBjb250ZW50VHlwZTogc3RyaW5nID0gJycpOiBCbG9iIHtcbiAgICBjb25zdCBzbGljZVNpemUgPSAxMDI0O1xuICAgIGNvbnN0IGJ5dGVDaGFyYWN0ZXJzOiBzdHJpbmcgPSBhdG9iKGJhc2U2NERhdGEpO1xuICAgIGNvbnN0IGJ5dGVzTGVuZ3RoOiBudW1iZXIgPSBieXRlQ2hhcmFjdGVycy5sZW5ndGg7XG4gICAgY29uc3Qgc2xpY2VzQ291bnQ6IG51bWJlciA9IE1hdGguY2VpbChieXRlc0xlbmd0aCAvIHNsaWNlU2l6ZSk7XG4gICAgY29uc3QgYnl0ZUFycmF5czogQXJyYXk8VWludDhBcnJheT4gPSBuZXcgQXJyYXkoc2xpY2VzQ291bnQpO1xuICAgIGZvciAobGV0IHNsaWNlSW5kZXggPSAwOyBzbGljZUluZGV4IDwgc2xpY2VzQ291bnQ7ICsrc2xpY2VJbmRleCkge1xuICAgICAgY29uc3QgYmVnaW46IG51bWJlciA9IHNsaWNlSW5kZXggKiBzbGljZVNpemU7XG4gICAgICBjb25zdCBlbmQ6IG51bWJlciA9IE1hdGgubWluKGJlZ2luICsgc2xpY2VTaXplLCBieXRlc0xlbmd0aCk7XG4gICAgICBjb25zdCBieXRlczogQXJyYXk8bnVtYmVyPiA9IG5ldyBBcnJheShlbmQgLSBiZWdpbik7XG4gICAgICBmb3IgKGxldCBvZmZzZXQgPSBiZWdpbiwgaSA9IDA7IG9mZnNldCA8IGVuZDsgKytpLCArK29mZnNldCkge1xuICAgICAgICBieXRlc1tpXSA9IGJ5dGVDaGFyYWN0ZXJzW29mZnNldF0uY2hhckNvZGVBdCgwKTtcbiAgICAgIH1cbiAgICAgIGJ5dGVBcnJheXNbc2xpY2VJbmRleF0gPSBuZXcgVWludDhBcnJheShieXRlcyk7XG4gICAgfVxuICAgIHJldHVybiBuZXcgQmxvYihieXRlQXJyYXlzLCB7IHR5cGU6IGNvbnRlbnRUeXBlIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIFByaXZhdGUgbWV0aG9kIHRvIGRvd25sb2FkIHRoZSBjdXJyZW50IGltYWdlIGZvciBhbGwgYnJvd3NlcnMgZXhjZXB0IGZvciBJRTExLlxuICAgKi9cbiAgcHJpdmF0ZSBkb3dubG9hZEltYWdlQWxsQnJvd3NlcnMoKTogdm9pZCB7XG4gICAgY29uc3QgbGluayA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2EnKTtcbiAgICBsZXQgaXNCYXNlNjQgPSBmYWxzZTtcbiAgICBsZXQgaW1nOiBzdHJpbmc7XG4gICAgLy8gY29udmVydCBhIFNhZmVSZXNvdXJjZVVybCB0byBhIHN0cmluZ1xuICAgIGlmICh0eXBlb2YgdGhpcy5jdXJyZW50SW1hZ2UubW9kYWwuaW1nID09PSAnc3RyaW5nJykge1xuICAgICAgaW1nID0gdGhpcy5jdXJyZW50SW1hZ2UubW9kYWwuaW1nIGFzIHN0cmluZztcbiAgICB9IGVsc2Uge1xuICAgICAgLy8gaWYgaXQncyBhIFNhZmVSZXNvdXJjZVVybFxuICAgICAgaW1nID0gdGhpcy5zYW5pdGl6ZXIuc2FuaXRpemUoU2VjdXJpdHlDb250ZXh0LlJFU09VUkNFX1VSTCwgdGhpcy5jdXJyZW50SW1hZ2UubW9kYWwuaW1nKSBhcyBzdHJpbmc7XG4gICAgfVxuICAgIGlmIChpbWcuaW5jbHVkZXMoJ2RhdGE6aW1hZ2UvJykgfHwgaW1nLmluY2x1ZGVzKCc7YmFzZTY0LCcpKSB7XG4gICAgICBjb25zdCBleHRlbnNpb246IHN0cmluZyA9IGltZy5yZXBsYWNlKCdkYXRhOmltYWdlLycsICcnKS5zcGxpdCgnO2Jhc2U2NCwnKVswXTtcbiAgICAgIGNvbnN0IHB1cmVCYXNlNjQ6IHN0cmluZyA9IGltZy5zcGxpdCgnO2Jhc2U2NCwnKVsxXTtcbiAgICAgIGNvbnN0IGJsb2I6IEJsb2IgPSB0aGlzLmJhc2U2NHRvQmxvYihwdXJlQmFzZTY0LCAnaW1hZ2UvJyArIGV4dGVuc2lvbik7XG4gICAgICBsaW5rLmhyZWYgPSBVUkwuY3JlYXRlT2JqZWN0VVJMKGJsb2IpO1xuICAgICAgaXNCYXNlNjQgPSB0cnVlO1xuICAgICAgbGluay5zZXRBdHRyaWJ1dGUoJ2Rvd25sb2FkJywgdGhpcy5nZXRGaWxlTmFtZSh0aGlzLmN1cnJlbnRJbWFnZSwgaXNCYXNlNjQsIGV4dGVuc2lvbikpO1xuICAgIH0gZWxzZSB7XG4gICAgICBsaW5rLmhyZWYgPSBpbWc7XG4gICAgICBsaW5rLnNldEF0dHJpYnV0ZSgnZG93bmxvYWQnLCB0aGlzLmdldEZpbGVOYW1lKHRoaXMuY3VycmVudEltYWdlLCBpc0Jhc2U2NCkpO1xuICAgIH1cbiAgICBkb2N1bWVudC5ib2R5LmFwcGVuZENoaWxkKGxpbmspO1xuICAgIGxpbmsuY2xpY2soKTtcbiAgICBkb2N1bWVudC5ib2R5LnJlbW92ZUNoaWxkKGxpbmspO1xuICB9XG5cbiAgLyoqXG4gICAqIFByaXZhdGUgbWV0aG9kIHRvIGRvd25sb2FkIHRoZSBjdXJyZW50IGltYWdlIG9ubHkgZm9yIElFMTEgdXNpbmdcbiAgICogY3VzdG9tIGphdmFzY3JpcHQncyBtZXRob2RzIGF2YWlsYWJsZSBvbmx5IG9uIElFLlxuICAgKi9cbiAgcHJpdmF0ZSBkb3dubG9hZEltYWdlT25seUlFb3JFZGdlKCk6IHZvaWQge1xuICAgIGlmIChpc1BsYXRmb3JtQnJvd3Nlcih0aGlzLnBsYXRmb3JtSWQpKSB7XG4gICAgICBjb25zdCByZXEgPSBuZXcgWE1MSHR0cFJlcXVlc3QoKTtcbiAgICAgIHJlcS5vcGVuKCdHRVQnLCB0aGlzLmN1cnJlbnRJbWFnZS5tb2RhbC5pbWcgYXMgc3RyaW5nLCB0cnVlKTtcbiAgICAgIHJlcS5yZXNwb25zZVR5cGUgPSAnYXJyYXlidWZmZXInO1xuICAgICAgcmVxLm9ubG9hZCA9IGV2ZW50ID0+IHtcbiAgICAgICAgY29uc3QgYmxvYiA9IG5ldyBCbG9iKFtyZXEucmVzcG9uc2VdLCB7IHR5cGU6ICdpbWFnZS9wbmcnIH0pO1xuICAgICAgICB3aW5kb3cubmF2aWdhdG9yLm1zU2F2ZUJsb2IoYmxvYiwgdGhpcy5nZXRGaWxlTmFtZSh0aGlzLmN1cnJlbnRJbWFnZSkpO1xuICAgICAgfTtcbiAgICAgIHJlcS5zZW5kKCk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFByaXZhdGUgbWV0aG9kIHRvIGdldCB0aGUgYEJ1dHRvbkV2ZW50YCB0byBlbWl0LCBtZXJnaW5nIHRoZSBpbnB1dCBgQnV0dG9uRXZlbnRgXG4gICAqIHdpdGggdGhlIGN1cnJlbnQgaW1hZ2UuXG4gICAqIEBwYXJhbSBCdXR0b25FdmVudCBldmVudCBwYXlsb2FkIHRvIHJldHVyblxuICAgKiBAcmV0dXJucyBCdXR0b25FdmVudCBldmVudCBwYXlsb2FkIHdpdGggdGhlIGN1cnJlbnQgaW1hZ2UgaW5jbHVkZWRcbiAgICovXG4gIHByaXZhdGUgZ2V0QnV0dG9uRXZlbnRUb0VtaXQoZXZlbnQ6IEJ1dHRvbkV2ZW50KTogQnV0dG9uRXZlbnQge1xuICAgIHJldHVybiBPYmplY3QuYXNzaWduKGV2ZW50LCB7IGltYWdlOiB0aGlzLmN1cnJlbnRJbWFnZSB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBQcml2YXRlIG1ldGhvZCB0byBnZXQgdGhlIGZpbGUgbmFtZSBmcm9tIGFuIGlucHV0IHBhdGguXG4gICAqIFRoaXMgaXMgdXNlZCBlaXRoZXIgdG8gZ2V0IHRoZSBpbWFnZSdzIG5hbWUgZnJvbSBpdHMgcGF0aCBvciBmcm9tIHRoZSBJbWFnZSBpdHNlbGYsXG4gICAqIGlmIHNwZWNpZmllZCBhcyAnZG93bmxvYWRGaWxlTmFtZScgYnkgdGhlIHVzZXIuXG4gICAqIEBwYXJhbSBJbWFnZSBpbWFnZSB0byBleHRyYWN0IGl0cyBmaWxlIG5hbWVcbiAgICogQHBhcmFtIGlzQmFzZTY0IGJvb2xlYW4gdG8gc2V0IGlmIHRoZSBpbWFnZSBpcyBhIGJhc2U2NCBmaWxlIG9yIG5vdC4gRmFsc2UgYnkgZGVmYXVsdC5cbiAgICogQHBhcmFtIGJhc2U2NEV4dGVuc2lvbiBzdHJpbmcgdG8gZm9yY2UgdGhlIGV4dGVuc2lvbiBvZiB0aGUgYmFzZTY0IGltYWdlLiBFbXB0eSBzdHJpbmcgYnkgZGVmYXVsdC5cbiAgICogQHJldHVybnMgc3RyaW5nIHN0cmluZyBmaWxlIG5hbWUgb2YgdGhlIGlucHV0IGltYWdlLlxuICAgKi9cbiAgcHJpdmF0ZSBnZXRGaWxlTmFtZShpbWFnZTogSW1hZ2UsIGlzQmFzZTY0OiBib29sZWFuID0gZmFsc2UsIGJhc2U2NEV4dGVuc2lvbjogc3RyaW5nID0gJycpOiBzdHJpbmcge1xuICAgIGlmICghaW1hZ2UubW9kYWwuZG93bmxvYWRGaWxlTmFtZSB8fCBpbWFnZS5tb2RhbC5kb3dubG9hZEZpbGVOYW1lLmxlbmd0aCA9PT0gMCkge1xuICAgICAgaWYgKGlzQmFzZTY0KSB7XG4gICAgICAgIHJldHVybiBgSW1hZ2UtJHtpbWFnZS5pZH0uJHtiYXNlNjRFeHRlbnNpb24gIT09ICcnID8gYmFzZTY0RXh0ZW5zaW9uIDogJ3BuZyd9YDtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiAoaW1hZ2UubW9kYWwuaW1nIGFzIHN0cmluZykucmVwbGFjZSgvXi4qW1xcXFxcXC9dLywgJycpO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gaW1hZ2UubW9kYWwuZG93bmxvYWRGaWxlTmFtZTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogUHJpdmF0ZSBtZXRob2QgdG8gaW5pdGlhbGl6ZSBgaW1hZ2VzYCBhcyBhcnJheSBvZiBgSW1hZ2Vgcy5cbiAgICogQWxzbywgaXQgd2lsbCBlbWl0IEltYWdlb3dtb2RhTW9kYWxFdmVudCB0byBzYXkgdGhhdCBpbWFnZXMgYXJlIGxvYWRlZC5cbiAgICovXG4gIHByaXZhdGUgaW5pdEltYWdlcygpOiB2b2lkIHtcbiAgICB0aGlzLm1vZGFsR2FsbGVyeVNlcnZpY2UuZW1pdEhhc0RhdGEobmV3IEltYWdlTW9kYWxFdmVudCh0aGlzLmlkLCBBY3Rpb24uTE9BRCwgdHJ1ZSkpO1xuICAgIHRoaXMuc2hvd0dhbGxlcnkgPSB0aGlzLmltYWdlcy5sZW5ndGggPiAwO1xuICB9XG5cbiAgLyoqXG4gICAqIFByaXZhdGUgbWV0aG9kIHRvIGVtaXQgZXZlbnRzIHdoZW4gZWl0aGVyIHRoZSBsYXN0IG9yIHRoZSBmaXJzdCBpbWFnZSBhcmUgdmlzaWJsZS5cbiAgICogQHBhcmFtIGFjdGlvbiBFbnVtIG9mIHR5cGUgQWN0aW9uIHRoYXQgcmVwcmVzZW50cyB0aGUgc291cmNlIG9mIHRoZSBldmVudCB0aGF0IGNoYW5nZWQgdGhlXG4gICAqICBjdXJyZW50IGltYWdlIHRvIHRoZSBmaXJzdCBvbmUgb3IgdGhlIGxhc3Qgb25lLlxuICAgKiBAcGFyYW0gaW5kZXhUb0NoZWNrIGlzIHRoZSBpbmRleCBudW1iZXIgb2YgdGhlIGltYWdlICh0aGUgZmlyc3Qgb3IgdGhlIGxhc3Qgb25lKS5cbiAgICovXG4gIHByaXZhdGUgZW1pdEJvdW5kYXJ5RXZlbnQoYWN0aW9uOiBBY3Rpb24sIGluZGV4VG9DaGVjazogbnVtYmVyKTogdm9pZCB7XG4gICAgLy8gdG8gZW1pdCBmaXJzdC9sYXN0IGV2ZW50XG4gICAgc3dpdGNoIChpbmRleFRvQ2hlY2spIHtcbiAgICAgIGNhc2UgMDpcbiAgICAgICAgdGhpcy5tb2RhbEdhbGxlcnlTZXJ2aWNlLmVtaXRGaXJzdEltYWdlKG5ldyBJbWFnZU1vZGFsRXZlbnQodGhpcy5pZCwgYWN0aW9uLCB0cnVlKSk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSB0aGlzLmltYWdlcy5sZW5ndGggLSAxOlxuICAgICAgICB0aGlzLm1vZGFsR2FsbGVyeVNlcnZpY2UuZW1pdExhc3RJbWFnZShuZXcgSW1hZ2VNb2RhbEV2ZW50KHRoaXMuaWQsIGFjdGlvbiwgdHJ1ZSkpO1xuICAgICAgICBicmVhaztcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogUHJpdmF0ZSBtZXRob2QgdG8gY2hlY2sgaWYgdGhpcyBsaWJyYXJ5IGlzIHJ1bm5pbmcgb25cbiAgICogTWljcm9zb2Z0IGJyb3dzZXJzIG9yIG5vdCAoaS5lLiBpdCBkZXRlY3RzIGJvdGggSUUxMSBhbmQgRWRnZSlcbiAgICogc3VwcG9ydGluZyBhbHNvIFNlcnZlci1TaWRlIFJlbmRlcmluZy5cbiAgICogSW5zcGlyZWQgYnkgaHR0cHM6Ly9tc2RuLm1pY3Jvc29mdC5jb20vaXQtaXQvbGlicmFyeS9oaDc3OTAxNih2PXZzLjg1KS5hc3B4XG4gICAqIEByZXR1cm5zIGFueSB0aGUgcmVzdWx0XG4gICAqL1xuICBwcml2YXRlIGlzSUVvckVkZ2UoKTogYm9vbGVhbiB7XG4gICAgaWYgKGlzUGxhdGZvcm1Ccm93c2VyKHRoaXMucGxhdGZvcm1JZCkpIHtcbiAgICAgIC8vIGlmIGJvdGggQmxvYiBjb25zdHJ1Y3RvciBhbmQgbXNTYXZlT3JPcGVuQmxvYiBhcmUgc3VwcG9ydGVkIGJ5IHRoZSBjdXJyZW50IGJyb3dzZXJcbiAgICAgIHJldHVybiAhIXdpbmRvdy5CbG9iICYmICEhd2luZG93Lm5hdmlnYXRvci5tc1NhdmVPck9wZW5CbG9iO1xuICAgIH1cbiAgICBpZiAoaXNQbGF0Zm9ybVNlcnZlcih0aGlzLnBsYXRmb3JtSWQpKSB7XG4gICAgICAvLyBzZXJ2ZXIgb25seVxuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICAgIHJldHVybiBmYWxzZTtcbiAgfVxufVxuIl19
|