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