@ks89/angular-modal-gallery 8.0.0-beta.5 → 9.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (161) hide show
  1. package/CHANGELOG.md +153 -0
  2. package/CONTRIBUTING.md +20 -38
  3. package/LICENSE +1 -1
  4. package/README.md +36 -42
  5. package/esm2020/ks89-angular-modal-gallery.mjs +5 -0
  6. package/esm2020/lib/components/accessibility-default.mjs +41 -0
  7. package/esm2020/lib/components/accessible.component.mjs +130 -0
  8. package/esm2020/lib/components/carousel/carousel-previews/carousel-previews.component.mjs +462 -0
  9. package/esm2020/lib/components/carousel/carousel.component.mjs +747 -0
  10. package/esm2020/lib/components/components.mjs +50 -0
  11. package/esm2020/lib/components/current-image/current-image.component.mjs +616 -0
  12. package/esm2020/lib/components/current-image/loading-spinner/loading-spinner.component.mjs +80 -0
  13. package/esm2020/lib/components/dots/dots.component.mjs +127 -0
  14. package/esm2020/lib/components/modal-gallery/modal-gallery-ref.mjs +103 -0
  15. package/esm2020/lib/components/modal-gallery/modal-gallery.component.mjs +523 -0
  16. package/esm2020/lib/components/modal-gallery/modal-gallery.service.mjs +187 -0
  17. package/esm2020/lib/components/modal-gallery/modal-gallery.tokens.mjs +26 -0
  18. package/esm2020/lib/components/plain-gallery/plain-gallery.component.mjs +249 -0
  19. package/esm2020/lib/components/previews/previews.component.mjs +332 -0
  20. package/esm2020/lib/components/upper-buttons/upper-buttons-default.mjs +76 -0
  21. package/esm2020/lib/components/upper-buttons/upper-buttons.component.mjs +249 -0
  22. package/esm2020/lib/directives/a-tag-bg-image.directive.mjs +78 -0
  23. package/esm2020/lib/directives/click-outside.directive.mjs +91 -0
  24. package/esm2020/lib/directives/description.directive.mjs +98 -0
  25. package/esm2020/lib/directives/direction.directive.mjs +73 -0
  26. package/esm2020/lib/directives/directives.mjs +49 -0
  27. package/esm2020/lib/directives/fallback-image.directive.mjs +59 -0
  28. package/esm2020/lib/directives/keyboard-navigation.directive.mjs +58 -0
  29. package/esm2020/lib/directives/margin.directive.mjs +84 -0
  30. package/esm2020/lib/directives/max-size.directive.mjs +75 -0
  31. package/esm2020/lib/directives/size.directive.mjs +76 -0
  32. package/{esm2015/lib/directives/size.directive.js → esm2020/lib/directives/wrap.directive.mjs} +23 -22
  33. package/esm2020/lib/modal-gallery.module.mjs +94 -0
  34. package/esm2020/lib/model/accessibility.interface.mjs +25 -0
  35. package/esm2020/lib/model/action.enum.mjs +36 -0
  36. package/esm2020/lib/model/buttons-config.interface.mjs +62 -0
  37. package/esm2020/lib/model/carousel-config.interface.mjs +25 -0
  38. package/esm2020/lib/model/carousel-image-config.interface.mjs +25 -0
  39. package/esm2020/lib/model/carousel-preview-config.interface.mjs +25 -0
  40. package/{esm2015/lib/model/keyboard-service-config.interface.js → esm2020/lib/model/current-image-config.interface.mjs} +2 -2
  41. package/esm2020/lib/model/description.interface.mjs +33 -0
  42. package/{esm2015/lib/model/preview-config.interface.js → esm2020/lib/model/dots-config.interface.mjs} +2 -2
  43. package/esm2020/lib/model/image-internal.class.mjs +35 -0
  44. package/esm2020/lib/model/image.class.mjs +54 -0
  45. package/esm2020/lib/model/interaction-event.interface.mjs +2 -0
  46. package/esm2020/lib/model/keyboard-config.interface.mjs +25 -0
  47. package/esm2020/lib/model/keyboard-service-config.interface.mjs +25 -0
  48. package/esm2020/lib/model/keyboard.enum.mjs +35 -0
  49. package/esm2020/lib/model/lib-config.interface.mjs +25 -0
  50. package/esm2020/lib/model/loading-config.interface.mjs +37 -0
  51. package/{esm2015/lib/model/dots-config.interface.js → esm2020/lib/model/max-size.interface.mjs} +2 -2
  52. package/{esm2015/lib/model/carousel-preview-config.interface.js → esm2020/lib/model/modal-gallery-config.interface.mjs} +2 -2
  53. package/esm2020/lib/model/plain-gallery-config.interface.mjs +55 -0
  54. package/{esm2015/lib/model/image-internal.class.js → esm2020/lib/model/play-config.interface.mjs} +3 -13
  55. package/esm2020/lib/model/preview-config.interface.mjs +25 -0
  56. package/esm2020/lib/model/size.interface.mjs +25 -0
  57. package/{esm2015/lib/model/carousel-config.interface.js → esm2020/lib/model/slide-config.interface.mjs} +2 -2
  58. package/esm2020/lib/services/config.service.mjs +396 -0
  59. package/esm2020/lib/services/id-validator.service.mjs +71 -0
  60. package/esm2020/lib/services/keyboard.service.mjs +111 -0
  61. package/esm2020/lib/utils/image.util.mjs +48 -0
  62. package/esm2020/lib/utils/user-input.util.mjs +104 -0
  63. package/esm2020/public-api.mjs +42 -0
  64. package/fesm2015/ks89-angular-modal-gallery.mjs +5782 -0
  65. package/fesm2015/ks89-angular-modal-gallery.mjs.map +1 -0
  66. package/{fesm2015/ks89-angular-modal-gallery.js → fesm2020/ks89-angular-modal-gallery.mjs} +3046 -2947
  67. package/fesm2020/ks89-angular-modal-gallery.mjs.map +1 -0
  68. package/ks89-angular-modal-gallery.d.ts +1 -24
  69. package/lib/components/accessible.component.d.ts +5 -2
  70. package/lib/components/carousel/carousel-previews/carousel-previews.component.d.ts +7 -11
  71. package/lib/components/carousel/carousel.component.d.ts +28 -67
  72. package/lib/components/current-image/current-image.component.d.ts +10 -4
  73. package/lib/components/current-image/loading-spinner/loading-spinner.component.d.ts +3 -0
  74. package/lib/components/dots/dots.component.d.ts +7 -0
  75. package/lib/components/modal-gallery/modal-gallery-ref.d.ts +35 -0
  76. package/lib/components/modal-gallery/modal-gallery.component.d.ts +58 -50
  77. package/lib/components/modal-gallery/modal-gallery.service.d.ts +60 -1
  78. package/lib/components/plain-gallery/plain-gallery.component.d.ts +18 -9
  79. package/lib/components/previews/previews.component.d.ts +9 -0
  80. package/lib/components/upper-buttons/upper-buttons.component.d.ts +8 -1
  81. package/lib/directives/a-tag-bg-image.directive.d.ts +3 -0
  82. package/lib/directives/click-outside.directive.d.ts +3 -0
  83. package/lib/directives/description.directive.d.ts +3 -0
  84. package/lib/directives/direction.directive.d.ts +3 -0
  85. package/lib/directives/fallback-image.directive.d.ts +6 -0
  86. package/lib/directives/keyboard-navigation.directive.d.ts +4 -1
  87. package/lib/directives/margin.directive.d.ts +3 -0
  88. package/lib/directives/max-size.directive.d.ts +3 -0
  89. package/lib/directives/size.directive.d.ts +5 -2
  90. package/lib/directives/wrap.directive.d.ts +4 -1
  91. package/lib/modal-gallery.module.d.ts +28 -0
  92. package/lib/model/carousel-config.interface.d.ts +0 -1
  93. package/lib/model/keyboard-config.interface.d.ts +4 -4
  94. package/lib/model/keyboard.enum.d.ts +11 -8
  95. package/lib/model/lib-config.interface.d.ts +20 -7
  96. package/lib/model/modal-gallery-config.interface.d.ts +2 -2
  97. package/lib/model/plain-gallery-config.interface.d.ts +1 -9
  98. package/lib/services/config.service.d.ts +3 -0
  99. package/lib/services/id-validator.service.d.ts +5 -1
  100. package/lib/services/keyboard.service.d.ts +5 -2
  101. package/lib/utils/user-input.util.d.ts +35 -26
  102. package/package.json +28 -16
  103. package/public-api.d.ts +2 -2
  104. package/bundles/ks89-angular-modal-gallery.umd.js +0 -5906
  105. package/bundles/ks89-angular-modal-gallery.umd.js.map +0 -1
  106. package/bundles/ks89-angular-modal-gallery.umd.min.js +0 -16
  107. package/bundles/ks89-angular-modal-gallery.umd.min.js.map +0 -1
  108. package/esm2015/ks89-angular-modal-gallery.js +0 -29
  109. package/esm2015/lib/components/accessibility-default.js +0 -41
  110. package/esm2015/lib/components/accessible.component.js +0 -127
  111. package/esm2015/lib/components/carousel/carousel-previews/carousel-previews.component.js +0 -466
  112. package/esm2015/lib/components/carousel/carousel.component.js +0 -772
  113. package/esm2015/lib/components/components.js +0 -50
  114. package/esm2015/lib/components/current-image/current-image.component.js +0 -590
  115. package/esm2015/lib/components/current-image/loading-spinner/loading-spinner.component.js +0 -80
  116. package/esm2015/lib/components/dots/dots.component.js +0 -127
  117. package/esm2015/lib/components/modal-gallery/modal-gallery-ref.js +0 -45
  118. package/esm2015/lib/components/modal-gallery/modal-gallery.component.js +0 -534
  119. package/esm2015/lib/components/modal-gallery/modal-gallery.service.js +0 -135
  120. package/esm2015/lib/components/modal-gallery/modal-gallery.tokens.js +0 -3
  121. package/esm2015/lib/components/plain-gallery/plain-gallery.component.js +0 -243
  122. package/esm2015/lib/components/previews/previews.component.js +0 -331
  123. package/esm2015/lib/components/upper-buttons/upper-buttons-default.js +0 -76
  124. package/esm2015/lib/components/upper-buttons/upper-buttons.component.js +0 -256
  125. package/esm2015/lib/directives/a-tag-bg-image.directive.js +0 -78
  126. package/esm2015/lib/directives/click-outside.directive.js +0 -85
  127. package/esm2015/lib/directives/description.directive.js +0 -99
  128. package/esm2015/lib/directives/direction.directive.js +0 -73
  129. package/esm2015/lib/directives/directives.js +0 -49
  130. package/esm2015/lib/directives/fallback-image.directive.js +0 -54
  131. package/esm2015/lib/directives/keyboard-navigation.directive.js +0 -52
  132. package/esm2015/lib/directives/margin.directive.js +0 -82
  133. package/esm2015/lib/directives/max-size.directive.js +0 -76
  134. package/esm2015/lib/directives/wrap.directive.js +0 -74
  135. package/esm2015/lib/modal-gallery.module.js +0 -64
  136. package/esm2015/lib/model/accessibility.interface.js +0 -25
  137. package/esm2015/lib/model/action.enum.js +0 -36
  138. package/esm2015/lib/model/buttons-config.interface.js +0 -66
  139. package/esm2015/lib/model/carousel-image-config.interface.js +0 -25
  140. package/esm2015/lib/model/current-image-config.interface.js +0 -25
  141. package/esm2015/lib/model/description.interface.js +0 -33
  142. package/esm2015/lib/model/image.class.js +0 -54
  143. package/esm2015/lib/model/interaction-event.interface.js +0 -2
  144. package/esm2015/lib/model/keyboard-config.interface.js +0 -25
  145. package/esm2015/lib/model/keyboard.enum.js +0 -35
  146. package/esm2015/lib/model/lib-config.interface.js +0 -25
  147. package/esm2015/lib/model/loading-config.interface.js +0 -37
  148. package/esm2015/lib/model/max-size.interface.js +0 -25
  149. package/esm2015/lib/model/modal-gallery-config.interface.js +0 -25
  150. package/esm2015/lib/model/plain-gallery-config.interface.js +0 -64
  151. package/esm2015/lib/model/play-config.interface.js +0 -25
  152. package/esm2015/lib/model/size.interface.js +0 -25
  153. package/esm2015/lib/model/slide-config.interface.js +0 -25
  154. package/esm2015/lib/services/config.service.js +0 -392
  155. package/esm2015/lib/services/id-validator.service.js +0 -71
  156. package/esm2015/lib/services/keyboard.service.js +0 -108
  157. package/esm2015/lib/utils/image.util.js +0 -48
  158. package/esm2015/lib/utils/user-input.util.js +0 -95
  159. package/esm2015/public-api.js +0 -46
  160. package/fesm2015/ks89-angular-modal-gallery.js.map +0 -1
  161. package/ks89-angular-modal-gallery.metadata.json +0 -1
@@ -1,466 +0,0 @@
1
- /*
2
- The MIT License (MIT)
3
-
4
- Copyright (c) 2017-2020 Stefano Cappa (Ks89)
5
-
6
- Permission is hereby granted, free of charge, to any person obtaining a copy
7
- of this software and associated documentation files (the "Software"), to deal
8
- in the Software without restriction, including without limitation the rights
9
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
- copies of the Software, and to permit persons to whom the Software is
11
- furnished to do so, subject to the following conditions:
12
-
13
- The above copyright notice and this permission notice shall be included in all
14
- copies or substantial portions of the Software.
15
-
16
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
- FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL THE
19
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
- SOFTWARE.
23
- */
24
- import { ChangeDetectionStrategy, ChangeDetectorRef, Component, EventEmitter, HostBinding, Input, Output } from '@angular/core';
25
- import { DomSanitizer } from '@angular/platform-browser';
26
- import { BreakpointObserver, Breakpoints } from '@angular/cdk/layout';
27
- import { AccessibleComponent } from '../../accessible.component';
28
- import { NEXT, PREV } from '../../../utils/user-input.util';
29
- import { getIndex } from '../../../utils/image.util';
30
- import { Action } from '../../../model/action.enum';
31
- import { ConfigService } from '../../../services/config.service';
32
- /**
33
- * Default max height of previews.
34
- */
35
- const DEFAULT_MAX_HEIGHT = '200px';
36
- /**
37
- * Component with image previews for carousel
38
- */
39
- export class CarouselPreviewsComponent extends AccessibleComponent {
40
- constructor(ref, breakpointObserver,
41
- // sanitizer is used only to sanitize style before add it to background property when legacyIE11Mode is enabled
42
- sanitizer, configService) {
43
- super();
44
- this.ref = ref;
45
- this.breakpointObserver = breakpointObserver;
46
- this.sanitizer = sanitizer;
47
- this.configService = configService;
48
- /**
49
- * Variable to change the max-width of the host component
50
- */
51
- this.hostMaxWidth = '100%';
52
- /**
53
- * Variable to set aria-label of the host component
54
- */
55
- this.ariaLabel = `Carousel previews`;
56
- /**
57
- * Output to emit the clicked preview. The payload contains the `InternalLibImage` associated to the clicked preview.
58
- */
59
- this.clickPreview = new EventEmitter();
60
- /**
61
- * Enum of type `Action` that represents a mouse click on a button.
62
- * Declared here to be used inside the template.
63
- */
64
- this.clickAction = Action.CLICK;
65
- /**
66
- * Enum of type `Action` that represents a keyboard action.
67
- * Declared here to be used inside the template.
68
- */
69
- this.keyboardAction = Action.KEYBOARD;
70
- /**
71
- * Array of `InternalLibImage` exposed to the template. This field is initialized
72
- * applying transformations, default values and so on to the input of the same type.
73
- */
74
- this.previews = [];
75
- /**
76
- * Variable with the preview's maxHeight
77
- */
78
- this.previewMaxHeight = DEFAULT_MAX_HEIGHT;
79
- // listen for width changes and update preview heights accordingly
80
- this.breakpointSubscription = breakpointObserver
81
- .observe([Breakpoints.XSmall, Breakpoints.Small, Breakpoints.Medium, Breakpoints.Large, Breakpoints.XLarge])
82
- .subscribe((result) => {
83
- if (!this.previewConfig || !this.previewConfig.breakpoints) {
84
- return;
85
- }
86
- if (result.breakpoints[Breakpoints.XSmall]) {
87
- this.updateHeight(this.previewConfig.breakpoints.xSmall);
88
- }
89
- else if (result.breakpoints[Breakpoints.Small]) {
90
- this.updateHeight(this.previewConfig.breakpoints.small);
91
- }
92
- else if (result.breakpoints[Breakpoints.Medium]) {
93
- this.updateHeight(this.previewConfig.breakpoints.medium);
94
- }
95
- else if (result.breakpoints[Breakpoints.Large]) {
96
- this.updateHeight(this.previewConfig.breakpoints.large);
97
- }
98
- else if (result.breakpoints[Breakpoints.XLarge]) {
99
- this.updateHeight(this.previewConfig.breakpoints.xLarge);
100
- }
101
- });
102
- }
103
- /**
104
- * Method to update the height of previews, passing the desired height as input.
105
- * @param configBreakpointHeight is a number that represent the desired height to set.
106
- */
107
- updateHeight(configBreakpointHeight) {
108
- if (this.previewConfig && this.previewConfig.maxHeight) {
109
- const heightNum = +this.previewConfig.maxHeight.replace('px', '').replace('%', '');
110
- this.previewMaxHeight = Math.min(configBreakpointHeight, heightNum) + 'px';
111
- }
112
- else {
113
- const heightNum = +DEFAULT_MAX_HEIGHT.replace('px', '').replace('%', '');
114
- this.previewMaxHeight = Math.min(configBreakpointHeight, heightNum) + 'px';
115
- }
116
- this.ref.markForCheck();
117
- }
118
- /**
119
- * Method ´ngOnInit´ to build `configPreview` applying a default value and also to
120
- * init the `previews` array.
121
- * This is an Angular's lifecycle hook, so its called automatically by Angular itself.
122
- * In particular, it's called only one time!!!
123
- */
124
- ngOnInit() {
125
- const libConfig = this.configService.getConfig(this.id);
126
- if (!libConfig) {
127
- throw new Error('Internal library error - libConfig must be defined');
128
- }
129
- this.carouselConfig = libConfig.carouselConfig;
130
- this.previewConfig = libConfig.carouselPreviewsConfig;
131
- this.accessibilityConfig = libConfig.accessibilityConfig;
132
- if (!this.previewConfig || !this.previewConfig.maxHeight || !this.previewConfig.breakpoints) {
133
- throw new Error('Internal library error - previewConfig must be defined');
134
- }
135
- // change the max-width of this component if there is a specified width !== 100% in carouselConfig
136
- if (this.carouselConfig && this.carouselConfig.maxWidth !== '100%') {
137
- this.hostMaxWidth = this.carouselConfig.maxWidth;
138
- }
139
- this.previewMaxHeight = this.previewConfig.maxHeight;
140
- // init previews based on currentImage and the full array of images
141
- this.initPreviews(this.currentImage, this.images);
142
- // apply custom height based on responsive breakpoints
143
- // This is required, because the breakpointSubscription is not triggered at creation,
144
- // but only when the width changes
145
- const isXsmallScreen = this.breakpointObserver.isMatched(Breakpoints.XSmall);
146
- const isSmallScreen = this.breakpointObserver.isMatched(Breakpoints.Small);
147
- const isMediumScreen = this.breakpointObserver.isMatched(Breakpoints.Medium);
148
- const isLargeScreen = this.breakpointObserver.isMatched(Breakpoints.Large);
149
- const isxLargeScreen = this.breakpointObserver.isMatched(Breakpoints.XLarge);
150
- if (isXsmallScreen) {
151
- this.updateHeight(this.previewConfig.breakpoints.xSmall);
152
- }
153
- else if (isSmallScreen) {
154
- this.updateHeight(this.previewConfig.breakpoints.small);
155
- }
156
- else if (isMediumScreen) {
157
- this.updateHeight(this.previewConfig.breakpoints.medium);
158
- }
159
- else if (isLargeScreen) {
160
- this.updateHeight(this.previewConfig.breakpoints.large);
161
- }
162
- else if (isxLargeScreen) {
163
- this.updateHeight(this.previewConfig.breakpoints.xLarge);
164
- }
165
- }
166
- /**
167
- * Method to check if an image is active (i.e. a preview image).
168
- * @param InternalLibImage preview is an image to check if it's active or not
169
- * @returns boolean true if is active, false otherwise
170
- */
171
- isActive(preview) {
172
- if (!preview || !this.currentImage) {
173
- return false;
174
- }
175
- return preview.id === this.currentImage.id;
176
- }
177
- /**
178
- * Method ´ngOnChanges´ to update `previews` array.
179
- * Also, both `start` and `end` local variables will be updated accordingly.
180
- * This is an Angular's lifecycle hook, so its called automatically by Angular itself.
181
- * In particular, it's called when any data-bound property of a directive changes!!!
182
- */
183
- ngOnChanges(changes) {
184
- const simpleChange = changes.currentImage;
185
- if (!simpleChange) {
186
- return;
187
- }
188
- const prev = simpleChange.previousValue;
189
- const current = simpleChange.currentValue;
190
- if (current && changes.images && changes.images.previousValue && changes.images.currentValue) {
191
- // I'm in this if statement, if input images are changed (for instance, because I removed one of them with the 'delete button',
192
- // or because users changed the images array while modal gallery is still open).
193
- // In this case, I have to re-init previews, because the input array of images is changed.
194
- this.initPreviews(current, changes.images.currentValue);
195
- }
196
- if (prev && current && prev.id !== current.id) {
197
- // to manage infinite sliding I have to reset both `start` and `end` at the beginning
198
- // to show again previews from the first image.
199
- // This happens when you navigate over the last image to return to the first one
200
- let prevIndex;
201
- let currentIndex;
202
- try {
203
- prevIndex = getIndex(prev, this.images);
204
- currentIndex = getIndex(current, this.images);
205
- }
206
- catch (err) {
207
- console.error('Cannot get previous and current image indexes in previews');
208
- throw err;
209
- }
210
- // apply a formula to get a values to be used to decide if go next, return back or stay without doing anything
211
- const calc = Math.floor((this.end - this.start) / 2) + this.start;
212
- if (prevIndex === this.images.length - 1 && currentIndex === 0) {
213
- // first image
214
- this.setBeginningIndexesPreviews();
215
- this.previews = this.images.filter((img, i) => i >= this.start && i < this.end);
216
- return;
217
- }
218
- // the same for the opposite case, when you navigate back from the fist image to go to the last one.
219
- if (prevIndex === 0 && currentIndex === this.images.length - 1) {
220
- // last image
221
- this.setEndIndexesPreviews();
222
- this.previews = this.images.filter((img, i) => i >= this.start && i < this.end);
223
- return;
224
- }
225
- if (this.previewConfig && this.previewConfig.number % 2 === 0) {
226
- if (calc > currentIndex) {
227
- this.previous();
228
- }
229
- else {
230
- this.next();
231
- }
232
- }
233
- else {
234
- if (calc > currentIndex) {
235
- this.previous();
236
- }
237
- if (calc < currentIndex) {
238
- this.next();
239
- }
240
- }
241
- }
242
- }
243
- /**
244
- * Method called by events from both keyboard and mouse on a preview.
245
- * This will trigger the `clickpreview` output with the input preview as its payload.
246
- * @param InternalLibImage preview that triggered this method
247
- * @param KeyboardEvent | MouseEvent event payload
248
- * @param Action that triggered this event (Action.NORMAL by default)
249
- */
250
- onImageEvent(preview, event, action = Action.NORMAL) {
251
- if (!this.previewConfig || !this.previewConfig.clickable) {
252
- return;
253
- }
254
- const clickedImageIndex = this.images.indexOf(preview);
255
- const result = super.handleImageEvent(event);
256
- if (result === NEXT) {
257
- this.clickPreview.emit({ action, result: clickedImageIndex });
258
- }
259
- else if (result === PREV) {
260
- this.clickPreview.emit({ action, result: clickedImageIndex });
261
- }
262
- }
263
- /**
264
- * Method called by events from both keyboard and mouse on a navigation arrow.
265
- * @param string direction of the navigation that can be either 'next' or 'prev'
266
- * @param KeyboardEvent | MouseEvent event payload
267
- */
268
- onNavigationEvent(direction, event) {
269
- const result = super.handleNavigationEvent(direction, event);
270
- if (result === NEXT) {
271
- this.next();
272
- }
273
- else if (result === PREV) {
274
- this.previous();
275
- }
276
- }
277
- /**
278
- * Method to get aria-label text for a preview image.
279
- * @param Image is the preview
280
- */
281
- getAriaLabel(preview) {
282
- if (!preview.plain) {
283
- return preview.modal.ariaLabel || '';
284
- }
285
- return preview.plain.ariaLabel || preview.modal.ariaLabel || '';
286
- }
287
- /**
288
- * Method to get title text for a preview image.
289
- * @param Image is the preview
290
- */
291
- getTitle(preview) {
292
- if (!preview.plain) {
293
- return preview.modal.title || '';
294
- }
295
- return preview.plain.title || preview.modal.title || '';
296
- }
297
- /**
298
- * Method to get alt text for a preview image.
299
- * @param Image is the preview
300
- */
301
- getAlt(preview) {
302
- if (!preview.plain) {
303
- return preview.modal.alt || '';
304
- }
305
- return preview.plain.alt || preview.modal.alt || '';
306
- }
307
- /**
308
- * Method used in the template to track ids in ngFor.
309
- * @param number index of the array
310
- * @param Image item of the array
311
- * @returns number the id of the item
312
- */
313
- trackById(index, item) {
314
- return item.id;
315
- }
316
- /**
317
- * Method used in template to sanitize an url when you need legacyIE11Mode.
318
- * In this way you can set an url as background of a div.
319
- * @param unsafeStyle is a string and represents the url to sanitize.
320
- * @param unsafeStyleFallback is a string and represents the fallback url to sanitize.
321
- * @returns a SafeStyle object that can be used in template without problems.
322
- */
323
- sanitizeUrlBgStyle(unsafeStyle, unsafeStyleFallback) {
324
- // Method used only to sanitize background-image style before add it to background property when legacyIE11Mode is enabled
325
- let bg = 'url(' + unsafeStyle + ')';
326
- if (!!unsafeStyleFallback) {
327
- // if a fallback image is defined, append it. In this way, it will be used by the browser as fallback.
328
- bg += ', ' + 'url(' + unsafeStyleFallback + ')';
329
- }
330
- return this.sanitizer.bypassSecurityTrustStyle(bg);
331
- }
332
- /**
333
- * Method to get the background-size value when IE11LegacyMode is enabled.
334
- * This prevent weired behaviour on IE11 when previews are really small, but original images (.png/.jgp/...) are big.
335
- * Using 'cover' it's not enough, because it's causing empty background in some cases.
336
- * After some experiments, I decided to use the double of the height and auto as width.
337
- */
338
- getIE11LegacyBgSize() {
339
- if (this.previewConfig && this.previewConfig.maxHeight) {
340
- const bgHeight = +this.previewConfig.maxHeight.replace('px', '');
341
- return '100% ' + bgHeight * 2 + 'px';
342
- }
343
- return 'cover';
344
- }
345
- /**
346
- * Method to cleanup resources. In fact, it cleans breakpointSubscription.
347
- * This is an Angular's lifecycle hook that is called when this component is destroyed.
348
- */
349
- ngOnDestroy() {
350
- if (this.breakpointSubscription) {
351
- this.breakpointSubscription.unsubscribe();
352
- }
353
- }
354
- /**
355
- * Private method to init previews based on the currentImage and the full array of images.
356
- * The current image in mandatory to show always the current preview (as highlighted).
357
- * @param InternalLibImage currentImage to decide how to show previews, because I always want to see the current image as highlighted
358
- * @param InternalLibImage[] images is the array of all images.
359
- */
360
- initPreviews(currentImage, images) {
361
- let index;
362
- try {
363
- index = getIndex(currentImage, images);
364
- }
365
- catch (err) {
366
- throw err;
367
- }
368
- switch (index) {
369
- case 0:
370
- // first image
371
- this.setBeginningIndexesPreviews();
372
- break;
373
- case images.length - 1:
374
- // last image
375
- this.setEndIndexesPreviews();
376
- break;
377
- // default:
378
- // // other images
379
- // // TODO unused because it starts always at image 0
380
- // this.setIndexesPreviews();
381
- // break;
382
- }
383
- this.previews = images.filter((img, i) => i >= this.start && i < this.end);
384
- }
385
- /**
386
- * Private method to init both `start` and `end` to the beginning.
387
- */
388
- setBeginningIndexesPreviews() {
389
- if (!this.previewConfig || this.previewConfig.number === undefined) {
390
- throw new Error('Internal library error - previewConfig and number must be defined');
391
- }
392
- this.start = 0;
393
- this.end = Math.min(this.previewConfig.number, this.images.length);
394
- }
395
- /**
396
- * Private method to init both `start` and `end` to the end.
397
- */
398
- setEndIndexesPreviews() {
399
- if (!this.previewConfig || this.previewConfig.number === undefined) {
400
- throw new Error('Internal library error - previewConfig and number must be defined');
401
- }
402
- this.start = this.images.length - 1 - (this.previewConfig.number - 1);
403
- this.end = this.images.length;
404
- }
405
- /**
406
- * Private method to update the visible previews navigating to the right (next).
407
- */
408
- next() {
409
- // check if nextImage should be blocked
410
- if (this.isPreventSliding(this.images.length - 1)) {
411
- return;
412
- }
413
- if (this.end === this.images.length) {
414
- return;
415
- }
416
- this.start++;
417
- this.end = Math.min(this.end + 1, this.images.length);
418
- this.previews = this.images.filter((img, i) => i >= this.start && i < this.end);
419
- }
420
- /**
421
- * Private method to update the visible previews navigating to the left (previous).
422
- */
423
- previous() {
424
- // check if prevImage should be blocked
425
- if (this.isPreventSliding(0)) {
426
- return;
427
- }
428
- if (this.start === 0) {
429
- return;
430
- }
431
- this.start = Math.max(this.start - 1, 0);
432
- this.end = Math.min(this.end - 1, this.images.length);
433
- this.previews = this.images.filter((img, i) => i >= this.start && i < this.end);
434
- }
435
- /**
436
- * Private method to block/permit sliding between previews.
437
- * @param number boundaryIndex is the first or the last index of `images` input array
438
- * @returns boolean if true block sliding, otherwise not
439
- */
440
- isPreventSliding(boundaryIndex) {
441
- return getIndex(this.currentImage, this.images) === boundaryIndex;
442
- }
443
- }
444
- CarouselPreviewsComponent.decorators = [
445
- { type: Component, args: [{
446
- selector: 'ks-carousel-previews',
447
- template: "<nav *ngIf=\"previewConfig?.visible\"\n class=\"previews-container\"\n [attr.aria-label]=\"accessibilityConfig?.carouselPreviewsContainerAriaLabel\"\n [title]=\"accessibilityConfig?.carouselPreviewsContainerTitle\">\n\n <a class=\"nav-left\"\n [attr.aria-label]=\"accessibilityConfig?.carouselPreviewScrollPrevAriaLabel\"\n [tabIndex]=\"previewConfig.arrows && start > 0 ? 0 : -1\" role=\"button\"\n (click)=\"onNavigationEvent('left', $event)\" (keyup)=\"onNavigationEvent('left', $event)\">\n <div class=\"inside {{previewConfig.arrows && start > 0 ? 'left-arrow-preview-image' : 'empty-arrow-preview-image'}}\"\n aria-hidden=\"true\"\n [title]=\"accessibilityConfig?.carouselPreviewScrollPrevTitle\"></div>\n </a>\n\n <div class=\"preview-inner-container\">\n <ng-container *ngFor=\"let preview of previews; trackBy: trackById; let index = index\">\n <ng-container *ngIf=\"!carouselConfig?.legacyIE11Mode; else legacyMode\">\n <img *ngIf=\"preview?.modal?.img\"\n class=\"inside preview-image{{isActive(preview) ? ' active' : ''}}{{!previewConfig.clickable ? ' unclickable' : ''}}\"\n [src]=\"preview.plain?.img ? preview.plain.img : preview.modal.img\"\n ksFallbackImage [fallbackImg]=\"preview.plain?.fallbackImg ? preview.plain.fallbackImg : preview.modal.fallbackImg\"\n ksSize [sizeConfig]=\"{width: previewConfig?.width,\n height: previewMaxHeight}\"\n [attr.aria-label]=\"getAriaLabel(preview)\"\n [title]=\"getTitle(preview)\"\n alt=\"{{getAlt(preview)}}\"\n [tabIndex]=\"0\" role=\"img\"\n (click)=\"onImageEvent(preview, $event, clickAction)\" (keyup)=\"onImageEvent(preview, $event, keyboardAction)\"/>\n </ng-container>\n <ng-template #legacyMode>\n <div *ngIf=\"preview?.modal?.img\"\n class=\"inside preview-ie11-image{{isActive(preview) ? ' active' : ''}}{{!previewConfig.clickable ? ' unclickable' : ''}}\"\n [style.background-color]=\"'transparent'\"\n [style.background-image]=\"sanitizeUrlBgStyle(preview.plain?.img ? preview.plain.img : preview.modal.img, preview.plain?.fallbackImg ? preview.plain.fallbackImg : preview.modal.fallbackImg)\"\n [style.background-position]=\"'center center'\"\n [style.background-size]=\"getIE11LegacyBgSize()\"\n [style.background-repeat]=\"'no-repeat'\"\n [style.background-attachment]=\"'scroll'\"\n ksSize [sizeConfig]=\"{width: previewConfig?.width,\n height: previewMaxHeight}\"\n [attr.aria-label]=\"getAriaLabel(preview)\"\n [title]=\"getTitle(preview)\"\n [tabIndex]=\"0\" role=\"img\"\n (click)=\"onImageEvent(preview, $event, clickAction)\" (keyup)=\"onImageEvent(preview, $event, keyboardAction)\"></div>\n </ng-template>\n </ng-container>\n </div>\n\n <a class=\"nav-right\"\n [attr.aria-label]=\"accessibilityConfig?.carouselPreviewScrollNextAriaLabel\"\n [tabIndex]=\"previewConfig.arrows && end < images.length ? 0 : -1\" role=\"button\"\n (click)=\"onNavigationEvent('right', $event)\" (keyup)=\"onNavigationEvent('right', $event)\">\n <div class=\"inside {{previewConfig.arrows && end < images.length ? 'right-arrow-preview-image' : 'empty-arrow-preview-image'}}\"\n aria-hidden=\"true\"\n [title]=\"accessibilityConfig?.carouselPreviewScrollNextTitle\"></div>\n </a>\n\n</nav>\n",
448
- changeDetection: ChangeDetectionStrategy.OnPush,
449
- styles: [":host{margin-bottom:3px;margin-top:3px;position:relative;width:100%}.previews-container{animation:fadein-semi-visible08 .8s;margin-bottom:0}.previews-container,.previews-container>.preview-inner-container{align-items:center;display:flex;flex-direction:row;justify-content:center}.previews-container>.preview-inner-container{flex-wrap:nowrap;width:100%}.previews-container>.preview-inner-container>.preview-image{cursor:pointer;object-fit:cover}.previews-container>.preview-inner-container>.preview-image.unclickable{cursor:not-allowed}.previews-container>.preview-inner-container>.preview-ie11-image{cursor:pointer}.previews-container>.preview-inner-container>.preview-ie11-image.unclickable{cursor:not-allowed}.previews-container .nav,.previews-container>.nav-left,.previews-container>.nav-right{color:#919191;cursor:pointer;position:absolute;top:calc(50% - 7px);transition:all .5s;z-index:1000}.previews-container .nav:hover,.previews-container>.nav-left:hover,.previews-container>.nav-right:hover{transform:scale(1.1)}.previews-container>.nav-left{left:10px;margin-right:10px}.previews-container>.nav-left>.left-arrow-preview-image{opacity:1}.previews-container>.nav-right{margin-left:10px;right:10px}.previews-container>.nav-right>.right-arrow-preview-image{opacity:1}", ".arrow-preview-image,.empty-arrow-preview-image,.left-arrow-preview-image,.right-arrow-preview-image{height:15px;opacity:.5;width:15px}.empty-arrow-preview-image{background:#000;opacity:0}.left-arrow-preview-image{background-image:url(\"data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iaXNvLTg4NTktMSI/PjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgdmVyc2lvbj0iMS4xIiBpZD0iQ2FwYV8xIiB4PSIwcHgiIHk9IjBweCIgdmlld0JveD0iMCAwIDQ3Ny4xNzUgNDc3LjE3NSIgc3R5bGU9ImVuYWJsZS1iYWNrZ3JvdW5kOm5ldyAwIDAgNDc3LjE3NSA0NzcuMTc1OyIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSIgd2lkdGg9IjUxMnB4IiBoZWlnaHQ9IjUxMnB4Ij48Zz48cGF0aCBkPSJNMTQ1LjE4OCwyMzguNTc1bDIxNS41LTIxNS41YzUuMy01LjMsNS4zLTEzLjgsMC0xOS4xcy0xMy44LTUuMy0xOS4xLDBsLTIyNS4xLDIyNS4xYy01LjMsNS4zLTUuMywxMy44LDAsMTkuMWwyMjUuMSwyMjUgICBjMi42LDIuNiw2LjEsNCw5LjUsNHM2LjktMS4zLDkuNS00YzUuMy01LjMsNS4zLTEzLjgsMC0xOS4xTDE0NS4xODgsMjM4LjU3NXoiIGZpbGw9IiNGRkZGRkYiLz48L2c+PGc+PC9nPjxnPjwvZz48Zz48L2c+PGc+PC9nPjxnPjwvZz48Zz48L2c+PGc+PC9nPjxnPjwvZz48Zz48L2c+PGc+PC9nPjxnPjwvZz48Zz48L2c+PGc+PC9nPjxnPjwvZz48Zz48L2c+PC9zdmc+\");background-size:15px;transition:all .5s}.left-arrow-preview-image:hover{transform:scale(1.2)}.right-arrow-preview-image{background-image:url(\"data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iaXNvLTg4NTktMSI/PjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgdmVyc2lvbj0iMS4xIiBpZD0iQ2FwYV8xIiB4PSIwcHgiIHk9IjBweCIgdmlld0JveD0iMCAwIDQ3Ny4xNzUgNDc3LjE3NSIgc3R5bGU9ImVuYWJsZS1iYWNrZ3JvdW5kOm5ldyAwIDAgNDc3LjE3NSA0NzcuMTc1OyIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSIgd2lkdGg9IjUxMnB4IiBoZWlnaHQ9IjUxMnB4Ij48Zz48cGF0aCBkPSJNMzYwLjczMSwyMjkuMDc1bC0yMjUuMS0yMjUuMWMtNS4zLTUuMy0xMy44LTUuMy0xOS4xLDBzLTUuMywxMy44LDAsMTkuMWwyMTUuNSwyMTUuNWwtMjE1LjUsMjE1LjUgICBjLTUuMyw1LjMtNS4zLDEzLjgsMCwxOS4xYzIuNiwyLjYsNi4xLDQsOS41LDRjMy40LDAsNi45LTEuMyw5LjUtNGwyMjUuMS0yMjUuMUMzNjUuOTMxLDI0Mi44NzUsMzY1LjkzMSwyMzQuMjc1LDM2MC43MzEsMjI5LjA3NXogICAiIGZpbGw9IiNGRkZGRkYiLz48L2c+PGc+PC9nPjxnPjwvZz48Zz48L2c+PGc+PC9nPjxnPjwvZz48Zz48L2c+PGc+PC9nPjxnPjwvZz48Zz48L2c+PGc+PC9nPjxnPjwvZz48Zz48L2c+PGc+PC9nPjxnPjwvZz48Zz48L2c+PC9zdmc+\");background-size:15px;transition:all .5s}.right-arrow-preview-image:hover{transform:scale(1.2)}"]
450
- },] }
451
- ];
452
- CarouselPreviewsComponent.ctorParameters = () => [
453
- { type: ChangeDetectorRef },
454
- { type: BreakpointObserver },
455
- { type: DomSanitizer },
456
- { type: ConfigService }
457
- ];
458
- CarouselPreviewsComponent.propDecorators = {
459
- hostMaxWidth: [{ type: HostBinding, args: ['style.max-width',] }],
460
- ariaLabel: [{ type: HostBinding, args: ['attr.aria-label',] }],
461
- id: [{ type: Input }],
462
- currentImage: [{ type: Input }],
463
- images: [{ type: Input }],
464
- clickPreview: [{ type: Output }]
465
- };
466
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2Fyb3VzZWwtcHJldmlld3MuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6Ii4uLy4uLy4uLy4uL3Byb2plY3RzL2tzODkvYW5ndWxhci1tb2RhbC1nYWxsZXJ5L3NyYy8iLCJzb3VyY2VzIjpbImxpYi9jb21wb25lbnRzL2Nhcm91c2VsL2Nhcm91c2VsLXByZXZpZXdzL2Nhcm91c2VsLXByZXZpZXdzLmNvbXBvbmVudC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQXNCRztBQUVILE9BQU8sRUFDTCx1QkFBdUIsRUFDdkIsaUJBQWlCLEVBQ2pCLFNBQVMsRUFDVCxZQUFZLEVBQ1osV0FBVyxFQUNYLEtBQUssRUFJTCxNQUFNLEVBR1AsTUFBTSxlQUFlLENBQUM7QUFDdkIsT0FBTyxFQUFFLFlBQVksRUFBYSxNQUFNLDJCQUEyQixDQUFDO0FBQ3BFLE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxXQUFXLEVBQW1CLE1BQU0scUJBQXFCLENBQUM7QUFJdkYsT0FBTyxFQUFFLG1CQUFtQixFQUFFLE1BQU0sNEJBQTRCLENBQUM7QUFRakUsT0FBTyxFQUFFLElBQUksRUFBRSxJQUFJLEVBQUUsTUFBTSxnQ0FBZ0MsQ0FBQztBQUM1RCxPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0sMkJBQTJCLENBQUM7QUFDckQsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLDRCQUE0QixDQUFDO0FBQ3BELE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSxrQ0FBa0MsQ0FBQztBQUdqRTs7R0FFRztBQUNILE1BQU0sa0JBQWtCLEdBQUcsT0FBTyxDQUFDO0FBRW5DOztHQUVHO0FBT0gsTUFBTSxPQUFPLHlCQUEwQixTQUFRLG1CQUFtQjtJQXNGaEUsWUFDVSxHQUFzQixFQUN0QixrQkFBc0M7SUFDOUMsK0dBQStHO0lBQ3ZHLFNBQXVCLEVBQ3ZCLGFBQTRCO1FBRXBDLEtBQUssRUFBRSxDQUFDO1FBTkEsUUFBRyxHQUFILEdBQUcsQ0FBbUI7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QUFDLENBQUMsQ0FBQztRQUN6QyxJQUFJLENBQUMsR0FBRyxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLEdBQUcsR0FBRyxDQUFDLEVBQUUsSUFBSSxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUV0RCxJQUFJLENBQUMsUUFBUSxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUMsR0FBcUIsRUFBRSxDQUFTLEVBQUUsRUFBRSxDQUFDLENBQUMsSUFBSSxJQUFJLENBQUMsS0FBSyxJQUFJLENBQUMsR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDNUcsQ0FBQztJQUVEOzs7O09BSUc7SUFDSyxnQkFBZ0IsQ0FBQyxhQUFxQjtRQUM1QyxPQUFPLFFBQVEsQ0FBQyxJQUFJLENBQUMsWUFBWSxFQUFFLElBQUksQ0FBQyxNQUFNLENBQUMsS0FBSyxhQUFhLENBQUM7SUFDcEUsQ0FBQzs7O1lBcmVGLFNBQVMsU0FBQztnQkFDVCxRQUFRLEVBQUUsc0JBQXNCO2dCQUVoQyxraEhBQXFDO2dCQUNyQyxlQUFlLEVBQUUsdUJBQXVCLENBQUMsTUFBTTs7YUFDaEQ7OztZQTVDQyxpQkFBaUI7WUFhVixrQkFBa0I7WUFEbEIsWUFBWTtZQWdCWixhQUFhOzs7MkJBcUJuQixXQUFXLFNBQUMsaUJBQWlCO3dCQU03QixXQUFXLFNBQUMsaUJBQWlCO2lCQU03QixLQUFLOzJCQU1MLEtBQUs7cUJBT0wsS0FBSzsyQkFPTCxNQUFNIiwic291cmNlc0NvbnRlbnQiOlsiLypcbiBUaGUgTUlUIExpY2Vuc2UgKE1JVClcblxuIENvcHlyaWdodCAoYykgMjAxNy0yMDIwIFN0ZWZhbm8gQ2FwcGEgKEtzODkpXG5cbiBQZXJtaXNzaW9uIGlzIGhlcmVieSBncmFudGVkLCBmcmVlIG9mIGNoYXJnZSwgdG8gYW55IHBlcnNvbiBvYnRhaW5pbmcgYSBjb3B5XG4gb2YgdGhpcyBzb2Z0d2FyZSBhbmQgYXNzb2NpYXRlZCBkb2N1bWVudGF0aW9uIGZpbGVzICh0aGUgXCJTb2Z0d2FyZVwiKSwgdG8gZGVhbFxuIGluIHRoZSBTb2Z0d2FyZSB3aXRob3V0IHJlc3RyaWN0aW9uLCBpbmNsdWRpbmcgd2l0aG91dCBsaW1pdGF0aW9uIHRoZSByaWdodHNcbiB0byB1c2UsIGNvcHksIG1vZGlmeSwgbWVyZ2UsIHB1Ymxpc2gsIGRpc3RyaWJ1dGUsIHN1YmxpY2Vuc2UsIGFuZC9vciBzZWxsXG4gY29waWVzIG9mIHRoZSBTb2Z0d2FyZSwgYW5kIHRvIHBlcm1pdCBwZXJzb25zIHRvIHdob20gdGhlIFNvZnR3YXJlIGlzXG4gZnVybmlzaGVkIHRvIGRvIHNvLCBzdWJqZWN0IHRvIHRoZSBmb2xsb3dpbmcgY29uZGl0aW9uczpcblxuIFRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlIGFuZCB0aGlzIHBlcm1pc3Npb24gbm90aWNlIHNoYWxsIGJlIGluY2x1ZGVkIGluIGFsbFxuIGNvcGllcyBvciBzdWJzdGFudGlhbCBwb3J0aW9ucyBvZiB0aGUgU29mdHdhcmUuXG5cbiBUSEUgU09GVFdBUkUgSVMgUFJPVklERUQgXCJBUyBJU1wiLCBXSVRIT1VUIFdBUlJBTlRZIE9GIEFOWSBLSU5ELCBFWFBSRVNTIE9SXG4gSU1QTElFRCwgSU5DTFVESU5HIEJVVCBOT1QgTElNSVRFRCBUTyBUSEUgV0FSUkFOVElFUyBPRiBNRVJDSEFOVEFCSUxJVFksXG4gRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQU5EIE5PTiBJTkZSSU5HRU1FTlQuIElOIE5PIEVWRU5UIFNIQUxMIFRIRVxuIEFVVEhPUlMgT1IgQ09QWVJJR0hUIEhPTERFUlMgQkUgTElBQkxFIEZPUiBBTlkgQ0xBSU0sIERBTUFHRVMgT1IgT1RIRVJcbiBMSUFCSUxJVFksIFdIRVRIRVIgSU4gQU4gQUNUSU9OIE9GIENPTlRSQUNULCBUT1JUIE9SIE9USEVSV0lTRSwgQVJJU0lORyBGUk9NLFxuIE9VVCBPRiBPUiBJTiBDT05ORUNUSU9OIFdJVEggVEhFIFNPRlRXQVJFIE9SIFRIRSBVU0UgT1IgT1RIRVIgREVBTElOR1MgSU4gVEhFXG4gU09GVFdBUkUuXG4gKi9cblxuaW1wb3J0IHtcbiAgQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3ksXG4gIENoYW5nZURldGVjdG9yUmVmLFxuICBDb21wb25lbnQsXG4gIEV2ZW50RW1pdHRlcixcbiAgSG9zdEJpbmRpbmcsXG4gIElucHV0LFxuICBPbkNoYW5nZXMsXG4gIE9uRGVzdHJveSxcbiAgT25Jbml0LFxuICBPdXRwdXQsXG4gIFNpbXBsZUNoYW5nZSxcbiAgU2ltcGxlQ2hhbmdlc1xufSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IERvbVNhbml0aXplciwgU2FmZVN0eWxlIH0gZnJvbSAnQGFuZ3VsYXIvcGxhdGZvcm0tYnJvd3Nlcic7XG5pbXBvcnQgeyBCcmVha3BvaW50T2JzZXJ2ZXIsIEJyZWFrcG9pbnRzLCBCcmVha3BvaW50U3RhdGUgfSBmcm9tICdAYW5ndWxhci9jZGsvbGF5b3V0JztcblxuaW1wb3J0IHsgU3Vic2NyaXB0aW9uIH0gZnJvbSAncnhqcyc7XG5cbmltcG9ydCB7IEFjY2Vzc2libGVDb21wb25lbnQgfSBmcm9tICcuLi8uLi9hY2Nlc3NpYmxlLmNvbXBvbmVudCc7XG5cbmltcG9ydCB7IEFjY2Vzc2liaWxpdHlDb25maWcgfSBmcm9tICcuLi8uLi8uLi9tb2RlbC9hY2Nlc3NpYmlsaXR5LmludGVyZmFjZSc7XG5pbXBvcnQgeyBJbWFnZSwgSW1hZ2VFdmVudCB9IGZyb20gJy4uLy4uLy4uL21vZGVsL2ltYWdlLmNsYXNzJztcbmltcG9ydCB7IEludGVybmFsTGliSW1hZ2UgfSBmcm9tICcuLi8uLi8uLi9tb2RlbC9pbWFnZS1pbnRlcm5hbC5jbGFzcyc7XG5pbXBvcnQgeyBDYXJvdXNlbFByZXZpZXdDb25maWcgfSBmcm9tICcuLi8uLi8uLi9tb2RlbC9jYXJvdXNlbC1wcmV2aWV3LWNvbmZpZy5pbnRlcmZhY2UnO1xuaW1wb3J0IHsgQ2Fyb3VzZWxDb25maWcgfSBmcm9tICcuLi8uLi8uLi9tb2RlbC9jYXJvdXNlbC1jb25maWcuaW50ZXJmYWNlJztcblxuaW1wb3J0IHsgTkVYVCwgUFJFViB9IGZyb20gJy4uLy4uLy4uL3V0aWxzL3VzZXItaW5wdXQudXRpbCc7XG5pbXBvcnQgeyBnZXRJbmRleCB9IGZyb20gJy4uLy4uLy4uL3V0aWxzL2ltYWdlLnV0aWwnO1xuaW1wb3J0IHsgQWN0aW9uIH0gZnJvbSAnLi4vLi4vLi4vbW9kZWwvYWN0aW9uLmVudW0nO1xuaW1wb3J0IHsgQ29uZmlnU2VydmljZSB9IGZyb20gJy4uLy4uLy4uL3NlcnZpY2VzL2NvbmZpZy5zZXJ2aWNlJztcbmltcG9ydCB7IExpYkNvbmZpZyB9IGZyb20gJy4uLy4uLy4uL21vZGVsL2xpYi1jb25maWcuaW50ZXJmYWNlJztcblxuLyoqXG4gKiBEZWZhdWx0IG1heCBoZWlnaHQgb2YgcHJldmlld3MuXG4gKi9cbmNvbnN0IERFRkFVTFRfTUFYX0hFSUdIVCA9ICcyMDBweCc7XG5cbi8qKlxuICogQ29tcG9uZW50IHdpdGggaW1hZ2UgcHJldmlld3MgZm9yIGNhcm91c2VsXG4gKi9cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ2tzLWNhcm91c2VsLXByZXZpZXdzJyxcbiAgc3R5bGVVcmxzOiBbJ2Nhcm91c2VsLXByZXZpZXdzLnNjc3MnLCAnLi4vLi4vcHJldmlld3MtYXJyb3dzLnNjc3MnXSxcbiAgdGVtcGxhdGVVcmw6ICdjYXJvdXNlbC1wcmV2aWV3cy5odG1sJyxcbiAgY2hhbmdlRGV0ZWN0aW9uOiBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneS5PblB1c2hcbn0pXG5leHBvcnQgY2xhc3MgQ2Fyb3VzZWxQcmV2aWV3c0NvbXBvbmVudCBleHRlbmRzIEFjY2Vzc2libGVDb21wb25lbnQgaW1wbGVtZW50cyBPbkluaXQsIE9uQ2hhbmdlcywgT25EZXN0cm95IHtcbiAgLyoqXG4gICAqIFZhcmlhYmxlIHRvIGNoYW5nZSB0aGUgbWF4LXdpZHRoIG9mIHRoZSBob3N0IGNvbXBvbmVudFxuICAgKi9cbiAgQEhvc3RCaW5kaW5nKCdzdHlsZS5tYXgtd2lkdGgnKVxuICBob3N0TWF4V2lkdGggPSAnMTAwJSc7XG5cbiAgLyoqXG4gICAqIFZhcmlhYmxlIHRvIHNldCBhcmlhLWxhYmVsIG9mIHRoZSBob3N0IGNvbXBvbmVudFxuICAgKi9cbiAgQEhvc3RCaW5kaW5nKCdhdHRyLmFyaWEtbGFiZWwnKVxuICBhcmlhTGFiZWwgPSBgQ2Fyb3VzZWwgcHJldmlld3NgO1xuXG4gIC8qKlxuICAgKiBUT0RPIHdyaXRlIGRvY1xuICAgKi9cbiAgQElucHV0KClcbiAgLy8gQHRzLWlnbm9yZVxuICBpZDogbnVtYmVyO1xuICAvKipcbiAgICogT2JqZWN0IG9mIHR5cGUgYEludGVybmFsTGliSW1hZ2VgIHRoYXQgcmVwcmVzZW50IHRoZSB2aXNpYmxlIGltYWdlLlxuICAgKi9cbiAgQElucHV0KClcbiAgLy8gQHRzLWlnbm9yZVxuICBjdXJyZW50SW1hZ2U6IEludGVybmFsTGliSW1hZ2U7XG4gIC8qKlxuICAgKiBBcnJheSBvZiBgSW50ZXJuYWxMaWJJbWFnZWAgdGhhdCByZXByZXNlbnQgdGhlIG1vZGVsIG9mIHRoaXMgbGlicmFyeSB3aXRoIGFsbCBpbWFnZXMsXG4gICAqIHRodW1icyBhbmQgc28gb24uXG4gICAqL1xuICBASW5wdXQoKVxuICAvLyBAdHMtaWdub3JlXG4gIGltYWdlczogSW50ZXJuYWxMaWJJbWFnZVtdO1xuXG4gIC8qKlxuICAgKiBPdXRwdXQgdG8gZW1pdCB0aGUgY2xpY2tlZCBwcmV2aWV3LiBUaGUgcGF5bG9hZCBjb250YWlucyB0aGUgYEludGVybmFsTGliSW1hZ2VgIGFzc29jaWF0ZWQgdG8gdGhlIGNsaWNrZWQgcHJldmlldy5cbiAgICovXG4gIEBPdXRwdXQoKVxuICBjbGlja1ByZXZpZXc6IEV2ZW50RW1pdHRlcjxJbWFnZUV2ZW50PiA9IG5ldyBFdmVudEVtaXR0ZXI8SW1hZ2VFdmVudD4oKTtcblxuICAvKipcbiAgICogT2JqZWN0IG9mIHR5cGUgYENhcm91c2VsQ29uZmlnYCB0byBpbml0IENhcm91c2VsQ29tcG9uZW50J3MgZmVhdHVyZXMuXG4gICAqIEZvciBpbnN0YW5jZSwgaXQgY29udGFpbnMgcGFyYW1ldGVycyB0byBjaGFuZ2UgdGhlIHN0eWxlLCBob3cgaXQgbmF2aWdhdGVzIGFuZCBzbyBvbi5cbiAgICovXG4gIGNhcm91c2VsQ29uZmlnOiBDYXJvdXNlbENvbmZpZyB8IHVuZGVmaW5lZDtcbiAgLyoqXG4gICAqIE9iamVjdCBvZiB0eXBlIGBDYXJvdXNlbFByZXZpZXdDb25maWdgIHRvIGluaXQgUHJldmlld3NDb21wb25lbnQncyBmZWF0dXJlcy5cbiAgICogRm9yIGluc3RhbmNlLCBpdCBjb250YWlucyBhIHBhcmFtIHRvIHNob3cvaGlkZSB0aGlzIGNvbXBvbmVudCwgc2l6ZXMuXG4gICAqL1xuICBwcmV2aWV3Q29uZmlnOiBDYXJvdXNlbFByZXZpZXdDb25maWcgfCB1bmRlZmluZWQ7XG4gIC8qKlxuICAgKiBPYmplY3Qgb2YgdHlwZSBgQWNjZXNzaWJpbGl0eUNvbmZpZ2AgdG8gaW5pdCBjdXN0b20gYWNjZXNzaWJpbGl0eSBmZWF0dXJlcy5cbiAgICogRm9yIGluc3RhbmNlLCBpdCBjb250YWlucyB0aXRsZXMsIGFsdCB0ZXh0cywgYXJpYS1sYWJlbHMgYW5kIHNvIG9uLlxuICAgKi9cbiAgYWNjZXNzaWJpbGl0eUNvbmZpZzogQWNjZXNzaWJpbGl0eUNvbmZpZyB8IHVuZGVmaW5lZDtcbiAgLyoqXG4gICAqIEVudW0gb2YgdHlwZSBgQWN0aW9uYCB0aGF0IHJlcHJlc2VudHMgYSBtb3VzZSBjbGljayBvbiBhIGJ1dHRvbi5cbiAgICogRGVjbGFyZWQgaGVyZSB0byBiZSB1c2VkIGluc2lkZSB0aGUgdGVtcGxhdGUuXG4gICAqL1xuICBjbGlja0FjdGlvbjogQWN0aW9uID0gQWN0aW9uLkNMSUNLO1xuICAvKipcbiAgICogRW51bSBvZiB0eXBlIGBBY3Rpb25gIHRoYXQgcmVwcmVzZW50cyBhIGtleWJvYXJkIGFjdGlvbi5cbiAgICogRGVjbGFyZWQgaGVyZSB0byBiZSB1c2VkIGluc2lkZSB0aGUgdGVtcGxhdGUuXG4gICAqL1xuICBrZXlib2FyZEFjdGlvbjogQWN0aW9uID0gQWN0aW9uLktFWUJPQVJEO1xuICAvKipcbiAgICogQXJyYXkgb2YgYEludGVybmFsTGliSW1hZ2VgIGV4cG9zZWQgdG8gdGhlIHRlbXBsYXRlLiBUaGlzIGZpZWxkIGlzIGluaXRpYWxpemVkXG4gICAqIGFwcGx5aW5nIHRyYW5zZm9ybWF0aW9ucywgZGVmYXVsdCB2YWx1ZXMgYW5kIHNvIG9uIHRvIHRoZSBpbnB1dCBvZiB0aGUgc2FtZSB0eXBlLlxuICAgKi9cbiAgcHJldmlld3M6IEludGVybmFsTGliSW1hZ2VbXSA9IFtdO1xuICAvKipcbiAgICogVmFyaWFibGUgd2l0aCB0aGUgcHJldmlldydzIG1heEhlaWdodFxuICAgKi9cbiAgcHJldmlld01heEhlaWdodDogc3RyaW5nID0gREVGQVVMVF9NQVhfSEVJR0hUO1xuICAvKipcbiAgICogU3RhcnQgaW5kZXggKGluY2x1c2l2ZSkgb2YgdGhlIGlucHV0IGltYWdlcyB1c2VkIHRvIGRpc3BsYXkgcHJldmlld3MuXG4gICAqL1xuICAvLyBAdHMtaWdub3JlXG4gIHN0YXJ0OiBudW1iZXI7XG4gIC8qKlxuICAgKiBFbmQgaW5kZXggKG5vbiBpbmNsdXNpdmUpIG9mIHRoZSBpbnB1dCBpbWFnZXMgdXNlZCB0byBkaXNwbGF5IHByZXZpZXdzLlxuICAgKi9cbiAgLy8gQHRzLWlnbm9yZVxuICBlbmQ6IG51bWJlcjtcblxuICBwcml2YXRlIHJlYWRvbmx5IGJyZWFrcG9pbnRTdWJzY3JpcHRpb246IFN1YnNjcmlwdGlvbjtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBwcml2YXRlIHJlZjogQ2hhbmdlRGV0ZWN0b3JSZWYsXG4gICAgcHJpdmF0ZSBicmVha3BvaW50T2JzZXJ2ZXI6IEJyZWFrcG9pbnRPYnNlcnZlcixcbiAgICAvLyBzYW5pdGl6ZXIgaXMgdXNlZCBvbmx5IHRvIHNhbml0aXplIHN0eWxlIGJlZm9yZSBhZGQgaXQgdG8gYmFja2dyb3VuZCBwcm9wZXJ0eSB3aGVuIGxlZ2FjeUlFMTFNb2RlIGlzIGVuYWJsZWRcbiAgICBwcml2YXRlIHNhbml0aXplcjogRG9tU2FuaXRpemVyLFxuICAgIHByaXZhdGUgY29uZmlnU2VydmljZTogQ29uZmlnU2VydmljZVxuICApIHtcbiAgICBzdXBlcigpO1xuXG4gICAgLy8gbGlzdGVuIGZvciB3aWR0aCBjaGFuZ2VzIGFuZCB1cGRhdGUgcHJldmlldyBoZWlnaHRzIGFjY29yZGluZ2x5XG4gICAgdGhpcy5icmVha3BvaW50U3Vic2NyaXB0aW9uID0gYnJlYWtwb2ludE9ic2VydmVyXG4gICAgICAub2JzZXJ2ZShbQnJlYWtwb2ludHMuWFNtYWxsLCBCcmVha3BvaW50cy5TbWFsbCwgQnJlYWtwb2ludHMuTWVkaXVtLCBCcmVha3BvaW50cy5MYXJnZSwgQnJlYWtwb2ludHMuWExhcmdlXSlcbiAgICAgIC5zdWJzY3JpYmUoKHJlc3VsdDogQnJlYWtwb2ludFN0YXRlKSA9PiB7XG4gICAgICAgIGlmICghdGhpcy5wcmV2aWV3Q29uZmlnIHx8ICF0aGlzLnByZXZpZXdDb25maWcuYnJlYWtwb2ludHMpIHtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHJlc3VsdC5icmVha3BvaW50c1tCcmVha3BvaW50cy5YU21hbGxdKSB7XG4gICAgICAgICAgdGhpcy51cGRhdGVIZWlnaHQodGhpcy5wcmV2aWV3Q29uZmlnLmJyZWFrcG9pbnRzLnhTbWFsbCk7XG4gICAgICAgIH0gZWxzZSBpZiAocmVzdWx0LmJyZWFrcG9pbnRzW0JyZWFrcG9pbnRzLlNtYWxsXSkge1xuICAgICAgICAgIHRoaXMudXBkYXRlSGVpZ2h0KHRoaXMucHJldmlld0NvbmZpZy5icmVha3BvaW50cy5zbWFsbCk7XG4gICAgICAgIH0gZWxzZSBpZiAocmVzdWx0LmJyZWFrcG9pbnRzW0JyZWFrcG9pbnRzLk1lZGl1bV0pIHtcbiAgICAgICAgICB0aGlzLnVwZGF0ZUhlaWdodCh0aGlzLnByZXZpZXdDb25maWcuYnJlYWtwb2ludHMubWVkaXVtKTtcbiAgICAgICAgfSBlbHNlIGlmIChyZXN1bHQuYnJlYWtwb2ludHNbQnJlYWtwb2ludHMuTGFyZ2VdKSB7XG4gICAgICAgICAgdGhpcy51cGRhdGVIZWlnaHQodGhpcy5wcmV2aWV3Q29uZmlnLmJyZWFrcG9pbnRzLmxhcmdlKTtcbiAgICAgICAgfSBlbHNlIGlmIChyZXN1bHQuYnJlYWtwb2ludHNbQnJlYWtwb2ludHMuWExhcmdlXSkge1xuICAgICAgICAgIHRoaXMudXBkYXRlSGVpZ2h0KHRoaXMucHJldmlld0NvbmZpZy5icmVha3BvaW50cy54TGFyZ2UpO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBNZXRob2QgdG8gdXBkYXRlIHRoZSBoZWlnaHQgb2YgcHJldmlld3MsIHBhc3NpbmcgdGhlIGRlc2lyZWQgaGVpZ2h0IGFzIGlucHV0LlxuICAgKiBAcGFyYW0gY29uZmlnQnJlYWtwb2ludEhlaWdodCBpcyBhIG51bWJlciB0aGF0IHJlcHJlc2VudCB0aGUgZGVzaXJlZCBoZWlnaHQgdG8gc2V0LlxuICAgKi9cbiAgcHJpdmF0ZSB1cGRhdGVIZWlnaHQoY29uZmlnQnJlYWtwb2ludEhlaWdodDogbnVtYmVyKTogdm9pZCB7XG4gICAgaWYgKHRoaXMucHJldmlld0NvbmZpZyAmJiB0aGlzLnByZXZpZXdDb25maWcubWF4SGVpZ2h0KSB7XG4gICAgICBjb25zdCBoZWlnaHROdW06IG51bWJlciA9ICt0aGlzLnByZXZpZXdDb25maWcubWF4SGVpZ2h0LnJlcGxhY2UoJ3B4JywgJycpLnJlcGxhY2UoJyUnLCAnJyk7XG4gICAgICB0aGlzLnByZXZpZXdNYXhIZWlnaHQgPSBNYXRoLm1pbihjb25maWdCcmVha3BvaW50SGVpZ2h0LCBoZWlnaHROdW0pICsgJ3B4JztcbiAgICB9IGVsc2Uge1xuICAgICAgY29uc3QgaGVpZ2h0TnVtOiBudW1iZXIgPSArREVGQVVMVF9NQVhfSEVJR0hULnJlcGxhY2UoJ3B4JywgJycpLnJlcGxhY2UoJyUnLCAnJyk7XG4gICAgICB0aGlzLnByZXZpZXdNYXhIZWlnaHQgPSBNYXRoLm1pbihjb25maWdCcmVha3BvaW50SGVpZ2h0LCBoZWlnaHROdW0pICsgJ3B4JztcbiAgICB9XG4gICAgdGhpcy5yZWYubWFya0ZvckNoZWNrKCk7XG4gIH1cblxuICAvKipcbiAgICogTWV0aG9kIMK0bmdPbkluaXTCtCB0byBidWlsZCBgY29uZmlnUHJldmlld2AgYXBwbHlpbmcgYSBkZWZhdWx0IHZhbHVlIGFuZCBhbHNvIHRvXG4gICAqIGluaXQgdGhlIGBwcmV2aWV3c2AgYXJyYXkuXG4gICAqIFRoaXMgaXMgYW4gQW5ndWxhcidzIGxpZmVjeWNsZSBob29rLCBzbyBpdHMgY2FsbGVkIGF1dG9tYXRpY2FsbHkgYnkgQW5ndWxhciBpdHNlbGYuXG4gICAqIEluIHBhcnRpY3VsYXIsIGl0J3MgY2FsbGVkIG9ubHkgb25lIHRpbWUhISFcbiAgICovXG4gIG5nT25Jbml0KCk6IHZvaWQge1xuICAgIGNvbnN0IGxpYkNvbmZpZzogTGliQ29uZmlnIHwgdW5kZWZpbmVkID0gdGhpcy5jb25maWdTZXJ2aWNlLmdldENvbmZpZyh0aGlzLmlkKTtcbiAgICBpZiAoIWxpYkNvbmZpZykge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnRlcm5hbCBsaWJyYXJ5IGVycm9yIC0gbGliQ29uZmlnIG11c3QgYmUgZGVmaW5lZCcpO1xuICAgIH1cbiAgICB0aGlzLmNhcm91c2VsQ29uZmlnID0gbGliQ29uZmlnLmNhcm91c2VsQ29uZmlnO1xuICAgIHRoaXMucHJldmlld0NvbmZpZyA9IGxpYkNvbmZpZy5jYXJvdXNlbFByZXZpZXdzQ29uZmlnO1xuICAgIHRoaXMuYWNjZXNzaWJpbGl0eUNvbmZpZyA9IGxpYkNvbmZpZy5hY2Nlc3NpYmlsaXR5Q29uZmlnO1xuXG4gICAgaWYgKCF0aGlzLnByZXZpZXdDb25maWcgfHwgIXRoaXMucHJldmlld0NvbmZpZy5tYXhIZWlnaHQgfHwgIXRoaXMucHJldmlld0NvbmZpZy5icmVha3BvaW50cykge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnRlcm5hbCBsaWJyYXJ5IGVycm9yIC0gcHJldmlld0NvbmZpZyBtdXN0IGJlIGRlZmluZWQnKTtcbiAgICB9XG4gICAgLy8gY2hhbmdlIHRoZSBtYXgtd2lkdGggb2YgdGhpcyBjb21wb25lbnQgaWYgdGhlcmUgaXMgYSBzcGVjaWZpZWQgd2lkdGggIT09IDEwMCUgaW4gY2Fyb3VzZWxDb25maWdcbiAgICBpZiAodGhpcy5jYXJvdXNlbENvbmZpZyAmJiB0aGlzLmNhcm91c2VsQ29uZmlnLm1heFdpZHRoICE9PSAnMTAwJScpIHtcbiAgICAgIHRoaXMuaG9zdE1heFdpZHRoID0gdGhpcy5jYXJvdXNlbENvbmZpZy5tYXhXaWR0aDtcbiAgICB9XG5cbiAgICB0aGlzLnByZXZpZXdNYXhIZWlnaHQgPSB0aGlzLnByZXZpZXdDb25maWcubWF4SGVpZ2h0O1xuICAgIC8vIGluaXQgcHJldmlld3MgYmFzZWQgb24gY3VycmVudEltYWdlIGFuZCB0aGUgZnVsbCBhcnJheSBvZiBpbWFnZXNcbiAgICB0aGlzLmluaXRQcmV2aWV3cyh0aGlzLmN1cnJlbnRJbWFnZSwgdGhpcy5pbWFnZXMpO1xuXG4gICAgLy8gYXBwbHkgY3VzdG9tIGhlaWdodCBiYXNlZCBvbiByZXNwb25zaXZlIGJyZWFrcG9pbnRzXG4gICAgLy8gVGhpcyBpcyByZXF1aXJlZCwgYmVjYXVzZSB0aGUgYnJlYWtwb2ludFN1YnNjcmlwdGlvbiBpcyBub3QgdHJpZ2dlcmVkIGF0IGNyZWF0aW9uLFxuICAgIC8vIGJ1dCBvbmx5IHdoZW4gdGhlIHdpZHRoIGNoYW5nZXNcbiAgICBjb25zdCBpc1hzbWFsbFNjcmVlbiA9IHRoaXMuYnJlYWtwb2ludE9ic2VydmVyLmlzTWF0Y2hlZChCcmVha3BvaW50cy5YU21hbGwpO1xuICAgIGNvbnN0IGlzU21hbGxTY3JlZW4gPSB0aGlzLmJyZWFrcG9pbnRPYnNlcnZlci5pc01hdGNoZWQoQnJlYWtwb2ludHMuU21hbGwpO1xuICAgIGNvbnN0IGlzTWVkaXVtU2NyZWVuID0gdGhpcy5icmVha3BvaW50T2JzZXJ2ZXIuaXNNYXRjaGVkKEJyZWFrcG9pbnRzLk1lZGl1bSk7XG4gICAgY29uc3QgaXNMYXJnZVNjcmVlbiA9IHRoaXMuYnJlYWtwb2ludE9ic2VydmVyLmlzTWF0Y2hlZChCcmVha3BvaW50cy5MYXJnZSk7XG4gICAgY29uc3QgaXN4TGFyZ2VTY3JlZW4gPSB0aGlzLmJyZWFrcG9pbnRPYnNlcnZlci5pc01hdGNoZWQoQnJlYWtwb2ludHMuWExhcmdlKTtcbiAgICBpZiAoaXNYc21hbGxTY3JlZW4pIHtcbiAgICAgIHRoaXMudXBkYXRlSGVpZ2h0KHRoaXMucHJldmlld0NvbmZpZy5icmVha3BvaW50cy54U21hbGwpO1xuICAgIH0gZWxzZSBpZiAoaXNTbWFsbFNjcmVlbikge1xuICAgICAgdGhpcy51cGRhdGVIZWlnaHQodGhpcy5wcmV2aWV3Q29uZmlnLmJyZWFrcG9pbnRzLnNtYWxsKTtcbiAgICB9IGVsc2UgaWYgKGlzTWVkaXVtU2NyZWVuKSB7XG4gICAgICB0aGlzLnVwZGF0ZUhlaWdodCh0aGlzLnByZXZpZXdDb25maWcuYnJlYWtwb2ludHMubWVkaXVtKTtcbiAgICB9IGVsc2UgaWYgKGlzTGFyZ2VTY3JlZW4pIHtcbiAgICAgIHRoaXMudXBkYXRlSGVpZ2h0KHRoaXMucHJldmlld0NvbmZpZy5icmVha3BvaW50cy5sYXJnZSk7XG4gICAgfSBlbHNlIGlmIChpc3hMYXJnZVNjcmVlbikge1xuICAgICAgdGhpcy51cGRhdGVIZWlnaHQodGhpcy5wcmV2aWV3Q29uZmlnLmJyZWFrcG9pbnRzLnhMYXJnZSk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIE1ldGhvZCB0byBjaGVjayBpZiBhbiBpbWFnZSBpcyBhY3RpdmUgKGkuZS4gYSBwcmV2aWV3IGltYWdlKS5cbiAgICogQHBhcmFtIEludGVybmFsTGliSW1hZ2UgcHJldmlldyBpcyBhbiBpbWFnZSB0byBjaGVjayBpZiBpdCdzIGFjdGl2ZSBvciBub3RcbiAgICogQHJldHVybnMgYm9vbGVhbiB0cnVlIGlmIGlzIGFjdGl2ZSwgZmFsc2Ugb3RoZXJ3aXNlXG4gICAqL1xuICBpc0FjdGl2ZShwcmV2aWV3OiBJbnRlcm5hbExpYkltYWdlKTogYm9vbGVhbiB7XG4gICAgaWYgKCFwcmV2aWV3IHx8ICF0aGlzLmN1cnJlbnRJbWFnZSkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICByZXR1cm4gcHJldmlldy5pZCA9PT0gdGhpcy5jdXJyZW50SW1hZ2UuaWQ7XG4gIH1cblxuICAvKipcbiAgICogTWV0aG9kIMK0bmdPbkNoYW5nZXPCtCB0byB1cGRhdGUgYHByZXZpZXdzYCBhcnJheS5cbiAgICogQWxzbywgYm90aCBgc3RhcnRgIGFuZCBgZW5kYCBsb2NhbCB2YXJpYWJsZXMgd2lsbCBiZSB1cGRhdGVkIGFjY29yZGluZ2x5LlxuICAgKiBUaGlzIGlzIGFuIEFuZ3VsYXIncyBsaWZlY3ljbGUgaG9vaywgc28gaXRzIGNhbGxlZCBhdXRvbWF0aWNhbGx5IGJ5IEFuZ3VsYXIgaXRzZWxmLlxuICAgKiBJbiBwYXJ0aWN1bGFyLCBpdCdzIGNhbGxlZCB3aGVuIGFueSBkYXRhLWJvdW5kIHByb3BlcnR5IG9mIGEgZGlyZWN0aXZlIGNoYW5nZXMhISFcbiAgICovXG4gIG5nT25DaGFuZ2VzKGNoYW5nZXM6IFNpbXBsZUNoYW5nZXMpOiB2b2lkIHtcbiAgICBjb25zdCBzaW1wbGVDaGFuZ2U6IFNpbXBsZUNoYW5nZSA9IGNoYW5nZXMuY3VycmVudEltYWdlO1xuICAgIGlmICghc2ltcGxlQ2hhbmdlKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY29uc3QgcHJldjogSW50ZXJuYWxMaWJJbWFnZSA9IHNpbXBsZUNoYW5nZS5wcmV2aW91c1ZhbHVlO1xuICAgIGNvbnN0IGN1cnJlbnQ6IEludGVybmFsTGliSW1hZ2UgPSBzaW1wbGVDaGFuZ2UuY3VycmVudFZhbHVlO1xuXG4gICAgaWYgKGN1cnJlbnQgJiYgY2hhbmdlcy5pbWFnZXMgJiYgY2hhbmdlcy5pbWFnZXMucHJldmlvdXNWYWx1ZSAmJiBjaGFuZ2VzLmltYWdlcy5jdXJyZW50VmFsdWUpIHtcbiAgICAgIC8vIEknbSBpbiB0aGlzIGlmIHN0YXRlbWVudCwgaWYgaW5wdXQgaW1hZ2VzIGFyZSBjaGFuZ2VkIChmb3IgaW5zdGFuY2UsIGJlY2F1c2UgSSByZW1vdmVkIG9uZSBvZiB0aGVtIHdpdGggdGhlICdkZWxldGUgYnV0dG9uJyxcbiAgICAgIC8vIG9yIGJlY2F1c2UgdXNlcnMgY2hhbmdlZCB0aGUgaW1hZ2VzIGFycmF5IHdoaWxlIG1vZGFsIGdhbGxlcnkgaXMgc3RpbGwgb3BlbikuXG4gICAgICAvLyBJbiB0aGlzIGNhc2UsIEkgaGF2ZSB0byByZS1pbml0IHByZXZpZXdzLCBiZWNhdXNlIHRoZSBpbnB1dCBhcnJheSBvZiBpbWFnZXMgaXMgY2hhbmdlZC5cbiAgICAgIHRoaXMuaW5pdFByZXZpZXdzKGN1cnJlbnQsIGNoYW5nZXMuaW1hZ2VzLmN1cnJlbnRWYWx1ZSk7XG4gICAgfVxuXG4gICAgaWYgKHByZXYgJiYgY3VycmVudCAmJiBwcmV2LmlkICE9PSBjdXJyZW50LmlkKSB7XG4gICAgICAvLyB0byBtYW5hZ2UgaW5maW5pdGUgc2xpZGluZyBJIGhhdmUgdG8gcmVzZXQgYm90aCBgc3RhcnRgIGFuZCBgZW5kYCBhdCB0aGUgYmVnaW5uaW5nXG4gICAgICAvLyB0byBzaG93IGFnYWluIHByZXZpZXdzIGZyb20gdGhlIGZpcnN0IGltYWdlLlxuICAgICAgLy8gVGhpcyBoYXBwZW5zIHdoZW4geW91IG5hdmlnYXRlIG92ZXIgdGhlIGxhc3QgaW1hZ2UgdG8gcmV0dXJuIHRvIHRoZSBmaXJzdCBvbmVcbiAgICAgIGxldCBwcmV2SW5kZXg6IG51bWJlcjtcbiAgICAgIGxldCBjdXJyZW50SW5kZXg6IG51bWJlcjtcbiAgICAgIHRyeSB7XG4gICAgICAgIHByZXZJbmRleCA9IGdldEluZGV4KHByZXYsIHRoaXMuaW1hZ2VzKTtcbiAgICAgICAgY3VycmVudEluZGV4ID0gZ2V0SW5kZXgoY3VycmVudCwgdGhpcy5pbWFnZXMpO1xuICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgIGNvbnNvbGUuZXJyb3IoJ0Nhbm5vdCBnZXQgcHJldmlvdXMgYW5kIGN1cnJlbnQgaW1hZ2UgaW5kZXhlcyBpbiBwcmV2aWV3cycpO1xuICAgICAgICB0aHJvdyBlcnI7XG4gICAgICB9XG5cbiAgICAgIC8vIGFwcGx5IGEgZm9ybXVsYSB0byBnZXQgYSB2YWx1ZXMgdG8gYmUgdXNlZCB0byBkZWNpZGUgaWYgZ28gbmV4dCwgcmV0dXJuIGJhY2sgb3Igc3RheSB3aXRob3V0IGRvaW5nIGFueXRoaW5nXG4gICAgICBjb25zdCBjYWxjID0gTWF0aC5mbG9vcigodGhpcy5lbmQgLSB0aGlzLnN0YXJ0KSAvIDIpICsgdGhpcy5zdGFydDtcblxuICAgICAgaWYgKHByZXZJbmRleCA9PT0gdGhpcy5pbWFnZXMubGVuZ3RoIC0gMSAmJiBjdXJyZW50SW5kZXggPT09IDApIHtcbiAgICAgICAgLy8gZmlyc3QgaW1hZ2VcbiAgICAgICAgdGhpcy5zZXRCZWdpbm5pbmdJbmRleGVzUHJldmlld3MoKTtcbiAgICAgICAgdGhpcy5wcmV2aWV3cyA9IHRoaXMuaW1hZ2VzLmZpbHRlcigoaW1nOiBJbnRlcm5hbExpYkltYWdlLCBpOiBudW1iZXIpID0+IGkgPj0gdGhpcy5zdGFydCAmJiBpIDwgdGhpcy5lbmQpO1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgICAvLyB0aGUgc2FtZSBmb3IgdGhlIG9wcG9zaXRlIGNhc2UsIHdoZW4geW91IG5hdmlnYXRlIGJhY2sgZnJvbSB0aGUgZmlzdCBpbWFnZSB0byBnbyB0byB0aGUgbGFzdCBvbmUuXG4gICAgICBpZiAocHJldkluZGV4ID09PSAwICYmIGN1cnJlbnRJbmRleCA9PT0gdGhpcy5pbWFnZXMubGVuZ3RoIC0gMSkge1xuICAgICAgICAvLyBsYXN0IGltYWdlXG4gICAgICAgIHRoaXMuc2V0RW5kSW5kZXhlc1ByZXZpZXdzKCk7XG4gICAgICAgIHRoaXMucHJldmlld3MgPSB0aGlzLmltYWdlcy5maWx0ZXIoKGltZzogSW50ZXJuYWxMaWJJbWFnZSwgaTogbnVtYmVyKSA9PiBpID49IHRoaXMuc3RhcnQgJiYgaSA8IHRoaXMuZW5kKTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICBpZiAodGhpcy5wcmV2aWV3Q29uZmlnICYmICh0aGlzLnByZXZpZXdDb25maWcubnVtYmVyIGFzIG51bWJlcikgJSAyID09PSAwKSB7XG4gICAgICAgIGlmIChjYWxjID4gY3VycmVudEluZGV4KSB7XG4gICAgICAgICAgdGhpcy5wcmV2aW91cygpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHRoaXMubmV4dCgpO1xuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBpZiAoY2FsYyA+IGN1cnJlbnRJbmRleCkge1xuICAgICAgICAgIHRoaXMucHJldmlvdXMoKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoY2FsYyA8IGN1cnJlbnRJbmRleCkge1xuICAgICAgICAgIHRoaXMubmV4dCgpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIE1ldGhvZCBjYWxsZWQgYnkgZXZlbnRzIGZyb20gYm90aCBrZXlib2FyZCBhbmQgbW91c2Ugb24gYSBwcmV2aWV3LlxuICAgKiBUaGlzIHdpbGwgdHJpZ2dlciB0aGUgYGNsaWNrcHJldmlld2Agb3V0cHV0IHdpdGggdGhlIGlucHV0IHByZXZpZXcgYXMgaXRzIHBheWxvYWQuXG4gICAqIEBwYXJhbSBJbnRlcm5hbExpYkltYWdlIHByZXZpZXcgdGhhdCB0cmlnZ2VyZWQgdGhpcyBtZXRob2RcbiAgICogQHBhcmFtIEtleWJvYXJkRXZlbnQgfCBNb3VzZUV2ZW50IGV2ZW50IHBheWxvYWRcbiAgICogQHBhcmFtIEFjdGlvbiB0aGF0IHRyaWdnZXJlZCB0aGlzIGV2ZW50IChBY3Rpb24uTk9STUFMIGJ5IGRlZmF1bHQpXG4gICAqL1xuICBvbkltYWdlRXZlbnQocHJldmlldzogSW50ZXJuYWxMaWJJbWFnZSwgZXZlbnQ6IEtleWJvYXJkRXZlbnQgfCBNb3VzZUV2ZW50LCBhY3Rpb246IEFjdGlvbiA9IEFjdGlvbi5OT1JNQUwpOiB2b2lkIHtcbiAgICBpZiAoIXRoaXMucHJldmlld0NvbmZpZyB8fCAhdGhpcy5wcmV2aWV3Q29uZmlnLmNsaWNrYWJsZSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBjb25zdCBjbGlja2VkSW1hZ2VJbmRleDogbnVtYmVyID0gdGhpcy5pbWFnZXMuaW5kZXhPZihwcmV2aWV3KTtcbiAgICBjb25zdCByZXN1bHQ6IG51bWJlciA9IHN1cGVyLmhhbmRsZUltYWdlRXZlbnQoZXZlbnQpO1xuICAgIGlmIChyZXN1bHQgPT09IE5FWFQpIHtcbiAgICAgIHRoaXMuY2xpY2tQcmV2aWV3LmVtaXQoeyBhY3Rpb24sIHJlc3VsdDogY2xpY2tlZEltYWdlSW5kZXggfSBhcyBJbWFnZUV2ZW50KTtcbiAgICB9IGVsc2UgaWYgKHJlc3VsdCA9PT0gUFJFVikge1xuICAgICAgdGhpcy5jbGlja1ByZXZpZXcuZW1pdCh7IGFjdGlvbiwgcmVzdWx0OiBjbGlja2VkSW1hZ2VJbmRleCB9IGFzIEltYWdlRXZlbnQpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBNZXRob2QgY2FsbGVkIGJ5IGV2ZW50cyBmcm9tIGJvdGgga2V5Ym9hcmQgYW5kIG1vdXNlIG9uIGEgbmF2aWdhdGlvbiBhcnJvdy5cbiAgICogQHBhcmFtIHN0cmluZyBkaXJlY3Rpb24gb2YgdGhlIG5hdmlnYXRpb24gdGhhdCBjYW4gYmUgZWl0aGVyICduZXh0JyBvciAncHJldidcbiAgICogQHBhcmFtIEtleWJvYXJkRXZlbnQgfCBNb3VzZUV2ZW50IGV2ZW50IHBheWxvYWRcbiAgICovXG4gIG9uTmF2aWdhdGlvbkV2ZW50KGRpcmVjdGlvbjogc3RyaW5nLCBldmVudDogS2V5Ym9hcmRFdmVudCB8IE1vdXNlRXZlbnQpOiB2b2lkIHtcbiAgICBjb25zdCByZXN1bHQ6IG51bWJlciA9IHN1cGVyLmhhbmRsZU5hdmlnYXRpb25FdmVudChkaXJlY3Rpb24sIGV2ZW50KTtcbiAgICBpZiAocmVzdWx0ID09PSBORVhUKSB7XG4gICAgICB0aGlzLm5leHQoKTtcbiAgICB9IGVsc2UgaWYgKHJlc3VsdCA9PT0gUFJFVikge1xuICAgICAgdGhpcy5wcmV2aW91cygpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBNZXRob2QgdG8gZ2V0IGFyaWEtbGFiZWwgdGV4dCBmb3IgYSBwcmV2aWV3IGltYWdlLlxuICAgKiBAcGFyYW0gSW1hZ2UgaXMgdGhlIHByZXZpZXdcbiAgICovXG4gIGdldEFyaWFMYWJlbChwcmV2aWV3OiBJbWFnZSk6IHN0cmluZyB7XG4gICAgaWYgKCFwcmV2aWV3LnBsYWluKSB7XG4gICAgICByZXR1cm4gcHJldmlldy5tb2RhbC5hcmlhTGFiZWwgfHwgJyc7XG4gICAgfVxuICAgIHJldHVybiBwcmV2aWV3LnBsYWluLmFyaWFMYWJlbCB8fCBwcmV2aWV3Lm1vZGFsLmFyaWFMYWJlbCB8fCAnJztcbiAgfVxuXG4gIC8qKlxuICAgKiBNZXRob2QgdG8gZ2V0IHRpdGxlIHRleHQgZm9yIGEgcHJldmlldyBpbWFnZS5cbiAgICogQHBhcmFtIEltYWdlIGlzIHRoZSBwcmV2aWV3XG4gICAqL1xuICBnZXRUaXRsZShwcmV2aWV3OiBJbWFnZSk6IHN0cmluZyB7XG4gICAgaWYgKCFwcmV2aWV3LnBsYWluKSB7XG4gICAgICByZXR1cm4gcHJldmlldy5tb2RhbC50aXRsZSB8fCAnJztcbiAgICB9XG4gICAgcmV0dXJuIHByZXZpZXcucGxhaW4udGl0bGUgfHwgcHJldmlldy5tb2RhbC50aXRsZSB8fCAnJztcbiAgfVxuXG4gIC8qKlxuICAgKiBNZXRob2QgdG8gZ2V0IGFsdCB0ZXh0IGZvciBhIHByZXZpZXcgaW1hZ2UuXG4gICAqIEBwYXJhbSBJbWFnZSBpcyB0aGUgcHJldmlld1xuICAgKi9cbiAgZ2V0QWx0KHByZXZpZXc6IEltYWdlKTogc3RyaW5nIHtcbiAgICBpZiAoIXByZXZpZXcucGxhaW4pIHtcbiAgICAgIHJldHVybiBwcmV2aWV3Lm1vZGFsLmFsdCB8fCAnJztcbiAgICB9XG4gICAgcmV0dXJuIHByZXZpZXcucGxhaW4uYWx0IHx8IHByZXZpZXcubW9kYWwuYWx0IHx8ICcnO1xuICB9XG5cbiAgLyoqXG4gICAqIE1ldGhvZCB1c2VkIGluIHRoZSB0ZW1wbGF0ZSB0byB0cmFjayBpZHMgaW4gbmdGb3IuXG4gICAqIEBwYXJhbSBudW1iZXIgaW5kZXggb2YgdGhlIGFycmF5XG4gICAqIEBwYXJhbSBJbWFnZSBpdGVtIG9mIHRoZSBhcnJheVxuICAgKiBAcmV0dXJucyBudW1iZXIgdGhlIGlkIG9mIHRoZSBpdGVtXG4gICAqL1xuICB0cmFja0J5SWQoaW5kZXg6IG51bWJlciwgaXRlbTogSW1hZ2UpOiBudW1iZXIge1xuICAgIHJldHVybiBpdGVtLmlkO1xuICB9XG5cbiAgLyoqXG4gICAqIE1ldGhvZCB1c2VkIGluIHRlbXBsYXRlIHRvIHNhbml0aXplIGFuIHVybCB3aGVuIHlvdSBuZWVkIGxlZ2FjeUlFMTFNb2RlLlxuICAgKiBJbiB0aGlzIHdheSB5b3UgY2FuIHNldCBhbiB1cmwgYXMgYmFja2dyb3VuZCBvZiBhIGRpdi5cbiAgICogQHBhcmFtIHVuc2FmZVN0eWxlIGlzIGEgc3RyaW5nIGFuZCByZXByZXNlbnRzIHRoZSB1cmwgdG8gc2FuaXRpemUuXG4gICAqIEBwYXJhbSB1bnNhZmVTdHlsZUZhbGxiYWNrIGlzIGEgc3RyaW5nIGFuZCByZXByZXNlbnRzIHRoZSBmYWxsYmFjayB1cmwgdG8gc2FuaXRpemUuXG4gICAqIEByZXR1cm5zIGEgU2FmZVN0eWxlIG9iamVjdCB0aGF0IGNhbiBiZSB1c2VkIGluIHRlbXBsYXRlIHdpdGhvdXQgcHJvYmxlbXMuXG4gICAqL1xuICBzYW5pdGl6ZVVybEJnU3R5bGUodW5zYWZlU3R5bGU6IHN0cmluZywgdW5zYWZlU3R5bGVGYWxsYmFjazogc3RyaW5nKTogU2FmZVN0eWxlIHtcbiAgICAvLyBNZXRob2QgdXNlZCBvbmx5IHRvIHNhbml0aXplIGJhY2tncm91bmQtaW1hZ2Ugc3R5bGUgYmVmb3JlIGFkZCBpdCB0byBiYWNrZ3JvdW5kIHByb3BlcnR5IHdoZW4gbGVnYWN5SUUxMU1vZGUgaXMgZW5hYmxlZFxuICAgIGxldCBiZzogc3RyaW5nID0gJ3VybCgnICsgdW5zYWZlU3R5bGUgKyAnKSc7XG4gICAgaWYgKCEhdW5zYWZlU3R5bGVGYWxsYmFjaykge1xuICAgICAgLy8gaWYgYSBmYWxsYmFjayBpbWFnZSBpcyBkZWZpbmVkLCBhcHBlbmQgaXQuIEluIHRoaXMgd2F5LCBpdCB3aWxsIGJlIHVzZWQgYnkgdGhlIGJyb3dzZXIgYXMgZmFsbGJhY2suXG4gICAgICBiZyArPSAnLCAnICsgJ3VybCgnICsgdW5zYWZlU3R5bGVGYWxsYmFjayArICcpJztcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuc2FuaXRpemVyLmJ5cGFzc1NlY3VyaXR5VHJ1c3RTdHlsZShiZyk7XG4gIH1cblxuICAvKipcbiAgICogTWV0aG9kIHRvIGdldCB0aGUgYmFja2dyb3VuZC1zaXplIHZhbHVlIHdoZW4gSUUxMUxlZ2FjeU1vZGUgaXMgZW5hYmxlZC5cbiAgICogVGhpcyBwcmV2ZW50IHdlaXJlZCBiZWhhdmlvdXIgb24gSUUxMSB3aGVuIHByZXZpZXdzIGFyZSByZWFsbHkgc21hbGwsIGJ1dCBvcmlnaW5hbCBpbWFnZXMgKC5wbmcvLmpncC8uLi4pIGFyZSBiaWcuXG4gICAqIFVzaW5nICdjb3ZlcicgaXQncyBub3QgZW5vdWdoLCBiZWNhdXNlIGl0J3MgY2F1c2luZyBlbXB0eSBiYWNrZ3JvdW5kIGluIHNvbWUgY2FzZXMuXG4gICAqIEFmdGVyIHNvbWUgZXhwZXJpbWVudHMsIEkgZGVjaWRlZCB0byB1c2UgdGhlIGRvdWJsZSBvZiB0aGUgaGVpZ2h0IGFuZCBhdXRvIGFzIHdpZHRoLlxuICAgKi9cbiAgZ2V0SUUxMUxlZ2FjeUJnU2l6ZSgpOiBzdHJpbmcge1xuICAgIGlmICh0aGlzLnByZXZpZXdDb25maWcgJiYgdGhpcy5wcmV2aWV3Q29uZmlnLm1heEhlaWdodCkge1xuICAgICAgY29uc3QgYmdIZWlnaHQ6IG51bWJlciA9ICt0aGlzLnByZXZpZXdDb25maWcubWF4SGVpZ2h0LnJlcGxhY2UoJ3B4JywgJycpO1xuICAgICAgcmV0dXJuICcxMDAlICcgKyBiZ0hlaWdodCAqIDIgKyAncHgnO1xuICAgIH1cbiAgICByZXR1cm4gJ2NvdmVyJztcbiAgfVxuXG4gIC8qKlxuICAgKiBNZXRob2QgdG8gY2xlYW51cCByZXNvdXJjZXMuIEluIGZhY3QsIGl0IGNsZWFucyBicmVha3BvaW50U3Vic2NyaXB0aW9uLlxuICAgKiBUaGlzIGlzIGFuIEFuZ3VsYXIncyBsaWZlY3ljbGUgaG9vayB0aGF0IGlzIGNhbGxlZCB3aGVuIHRoaXMgY29tcG9uZW50IGlzIGRlc3Ryb3llZC5cbiAgICovXG4gIG5nT25EZXN0cm95KCk6IHZvaWQge1xuICAgIGlmICh0aGlzLmJyZWFrcG9pbnRTdWJzY3JpcHRpb24pIHtcbiAgICAgIHRoaXMuYnJlYWtwb2ludFN1YnNjcmlwdGlvbi51bnN1YnNjcmliZSgpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBQcml2YXRlIG1ldGhvZCB0byBpbml0IHByZXZpZXdzIGJhc2VkIG9uIHRoZSBjdXJyZW50SW1hZ2UgYW5kIHRoZSBmdWxsIGFycmF5IG9mIGltYWdlcy5cbiAgICogVGhlIGN1cnJlbnQgaW1hZ2UgaW4gbWFuZGF0b3J5IHRvIHNob3cgYWx3YXlzIHRoZSBjdXJyZW50IHByZXZpZXcgKGFzIGhpZ2hsaWdodGVkKS5cbiAgICogQHBhcmFtIEludGVybmFsTGliSW1hZ2UgY3VycmVudEltYWdlIHRvIGRlY2lkZSBob3cgdG8gc2hvdyBwcmV2aWV3cywgYmVjYXVzZSBJIGFsd2F5cyB3YW50IHRvIHNlZSB0aGUgY3VycmVudCBpbWFnZSBhcyBoaWdobGlnaHRlZFxuICAgKiBAcGFyYW0gSW50ZXJuYWxMaWJJbWFnZVtdIGltYWdlcyBpcyB0aGUgYXJyYXkgb2YgYWxsIGltYWdlcy5cbiAgICovXG4gIHByaXZhdGUgaW5pdFByZXZpZXdzKGN1cnJlbnRJbWFnZTogSW50ZXJuYWxMaWJJbWFnZSwgaW1hZ2VzOiBJbnRlcm5hbExpYkltYWdlW10pOiB2b2lkIHtcbiAgICBsZXQgaW5kZXg6IG51bWJlcjtcbiAgICB0cnkge1xuICAgICAgaW5kZXggPSBnZXRJbmRleChjdXJyZW50SW1hZ2UsIGltYWdlcyk7XG4gICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICB0aHJvdyBlcnI7XG4gICAgfVxuICAgIHN3aXRjaCAoaW5kZXgpIHtcbiAgICAgIGNhc2UgMDpcbiAgICAgICAgLy8gZmlyc3QgaW1hZ2VcbiAgICAgICAgdGhpcy5zZXRCZWdpbm5pbmdJbmRleGVzUHJldmlld3MoKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIGltYWdlcy5sZW5ndGggLSAxOlxuICAgICAgICAvLyBsYXN0IGltYWdlXG4gICAgICAgIHRoaXMuc2V0RW5kSW5kZXhlc1ByZXZpZXdzKCk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgLy8gZGVmYXVsdDpcbiAgICAgIC8vICAgLy8gb3RoZXIgaW1hZ2VzXG4gICAgICAvLyAgIC8vIFRPRE8gdW51c2VkIGJlY2F1c2UgaXQgc3RhcnRzIGFsd2F5cyBhdCBpbWFnZSAwXG4gICAgICAvLyAgIHRoaXMuc2V0SW5kZXhlc1ByZXZpZXdzKCk7XG4gICAgICAvLyAgIGJyZWFrO1xuICAgIH1cbiAgICB0aGlzLnByZXZpZXdzID0gaW1hZ2VzLmZpbHRlcigoaW1nOiBJbnRlcm5hbExpYkltYWdlLCBpOiBudW1iZXIpID0+IGkgPj0gdGhpcy5zdGFydCAmJiBpIDwgdGhpcy5lbmQpO1xuICB9XG5cbiAgLyoqXG4gICAqIFByaXZhdGUgbWV0aG9kIHRvIGluaXQgYm90aCBgc3RhcnRgIGFuZCBgZW5kYCB0byB0aGUgYmVnaW5uaW5nLlxuICAgKi9cbiAgcHJpdmF0ZSBzZXRCZWdpbm5pbmdJbmRleGVzUHJldmlld3MoKTogdm9pZCB7XG4gICAgaWYgKCF0aGlzLnByZXZpZXdDb25maWcgfHwgdGhpcy5wcmV2aWV3Q29uZmlnLm51bWJlciA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludGVybmFsIGxpYnJhcnkgZXJyb3IgLSBwcmV2aWV3Q29uZmlnIGFuZCBudW1iZXIgbXVzdCBiZSBkZWZpbmVkJyk7XG4gICAgfVxuXG4gICAgdGhpcy5zdGFydCA9IDA7XG4gICAgdGhpcy5lbmQgPSBNYXRoLm1pbih0aGlzLnByZXZpZXdDb25maWcubnVtYmVyIGFzIG51bWJlciwgdGhpcy5pbWFnZXMubGVuZ3RoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBQcml2YXRlIG1ldGhvZCB0byBpbml0IGJvdGggYHN0YXJ0YCBhbmQgYGVuZGAgdG8gdGhlIGVuZC5cbiAgICovXG4gIHByaXZhdGUgc2V0RW5kSW5kZXhlc1ByZXZpZXdzKCk6IHZvaWQge1xuICAgIGlmICghdGhpcy5wcmV2aWV3Q29uZmlnIHx8IHRoaXMucHJldmlld0NvbmZpZy5udW1iZXIgPT09IHVuZGVmaW5lZCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnRlcm5hbCBsaWJyYXJ5IGVycm9yIC0gcHJldmlld0NvbmZpZyBhbmQgbnVtYmVyIG11c3QgYmUgZGVmaW5lZCcpO1xuICAgIH1cblxuICAgIHRoaXMuc3RhcnQgPSB0aGlzLmltYWdlcy5sZW5ndGggLSAxIC0gKCh0aGlzLnByZXZpZXdDb25maWcubnVtYmVyIGFzIG51bWJlcikgLSAxKTtcbiAgICB0aGlzLmVuZCA9IHRoaXMuaW1hZ2VzLmxlbmd0aDtcbiAgfVxuXG4gIC8qKlxuICAgKiBQcml2YXRlIG1ldGhvZCB0byB1cGRhdGUgdGhlIHZpc2libGUgcHJldmlld3MgbmF2aWdhdGluZyB0byB0aGUgcmlnaHQgKG5leHQpLlxuICAgKi9cbiAgcHJpdmF0ZSBuZXh0KCk6IHZvaWQge1xuICAgIC8vIGNoZWNrIGlmIG5leHRJbWFnZSBzaG91bGQgYmUgYmxvY2tlZFxuICAgIGlmICh0aGlzLmlzUHJldmVudFNsaWRpbmcodGhpcy5pbWFnZXMubGVuZ3RoIC0gMSkpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZiAodGhpcy5lbmQgPT09IHRoaXMuaW1hZ2VzLmxlbmd0aCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHRoaXMuc3RhcnQrKztcbiAgICB0aGlzLmVuZCA9IE1hdGgubWluKHRoaXMuZW5kICsgMSwgdGhpcy5pbWFnZXMubGVuZ3RoKTtcblxuICAgIHRoaXMucHJldmlld3MgPSB0aGlzLmltYWdlcy5maWx0ZXIoKGltZzogSW50ZXJuYWxMaWJJbWFnZSwgaTogbnVtYmVyKSA9PiBpID49IHRoaXMuc3RhcnQgJiYgaSA8IHRoaXMuZW5kKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBQcml2YXRlIG1ldGhvZCB0byB1cGRhdGUgdGhlIHZpc2libGUgcHJldmlld3MgbmF2aWdhdGluZyB0byB0aGUgbGVmdCAocHJldmlvdXMpLlxuICAgKi9cbiAgcHJpdmF0ZSBwcmV2aW91cygpOiB2b2lkIHtcbiAgICAvLyBjaGVjayBpZiBwcmV2SW1hZ2Ugc2hvdWxkIGJlIGJsb2NrZWRcbiAgICBpZiAodGhpcy5pc1ByZXZlbnRTbGlkaW5nKDApKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgaWYgKHRoaXMuc3RhcnQgPT09IDApIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB0aGlzLnN0YXJ0ID0gTWF0aC5tYXgodGhpcy5zdGFydCAtIDEsIDApO1xuICAgIHRoaXMuZW5kID0gTWF0aC5taW4odGhpcy5lbmQgLSAxLCB0aGlzLmltYWdlcy5sZW5ndGgpO1xuXG4gICAgdGhpcy5wcmV2aWV3cyA9IHRoaXMuaW1hZ2VzLmZpbHRlcigoaW1nOiBJbnRlcm5hbExpYkltYWdlLCBpOiBudW1iZXIpID0+IGkgPj0gdGhpcy5zdGFydCAmJiBpIDwgdGhpcy5lbmQpO1xuICB9XG5cbiAgLyoqXG4gICAqIFByaXZhdGUgbWV0aG9kIHRvIGJsb2NrL3Blcm1pdCBzbGlkaW5nIGJldHdlZW4gcHJldmlld3MuXG4gICAqIEBwYXJhbSBudW1iZXIgYm91bmRhcnlJbmRleCBpcyB0aGUgZmlyc3Qgb3IgdGhlIGxhc3QgaW5kZXggb2YgYGltYWdlc2AgaW5wdXQgYXJyYXlcbiAgICogQHJldHVybnMgYm9vbGVhbiBpZiB0cnVlIGJsb2NrIHNsaWRpbmcsIG90aGVyd2lzZSBub3RcbiAgICovXG4gIHByaXZhdGUgaXNQcmV2ZW50U2xpZGluZyhib3VuZGFyeUluZGV4OiBudW1iZXIpOiBib29sZWFuIHtcbiAgICByZXR1cm4gZ2V0SW5kZXgodGhpcy5jdXJyZW50SW1hZ2UsIHRoaXMuaW1hZ2VzKSA9PT0gYm91bmRhcnlJbmRleDtcbiAgfVxufVxuIl19