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