stream-chat-angular 6.0.0-beta.5 → 6.0.0-rc.2

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 (202) hide show
  1. package/README.md +2 -2
  2. package/assets/i18n/en.d.ts +0 -1
  3. package/assets/version.d.ts +1 -1
  4. package/{esm2022 → esm2020}/assets/i18n/en.mjs +1 -2
  5. package/{esm2022 → esm2020}/assets/version.mjs +2 -2
  6. package/esm2020/lib/attachment-configuration.service.mjs +182 -0
  7. package/esm2020/lib/attachment-list/attachment-list.component.mjs +232 -0
  8. package/esm2020/lib/attachment-preview-list/attachment-preview-list.component.mjs +55 -0
  9. package/esm2020/lib/attachment.service.mjs +481 -0
  10. package/esm2020/lib/avatar/avatar.component.mjs +160 -0
  11. package/esm2020/lib/avatar-placeholder/avatar-placeholder.component.mjs +66 -0
  12. package/esm2020/lib/channel/channel.component.mjs +45 -0
  13. package/esm2020/lib/channel-header/channel-header.component.mjs +72 -0
  14. package/esm2020/lib/channel-list/channel-list.component.mjs +47 -0
  15. package/esm2020/lib/channel-preview/channel-preview.component.mjs +155 -0
  16. package/esm2020/lib/channel-query.mjs +77 -0
  17. package/esm2020/lib/channel.service.mjs +1561 -0
  18. package/esm2020/lib/chat-client.service.mjs +233 -0
  19. package/esm2020/lib/custom-templates.service.mjs +244 -0
  20. package/{esm2022 → esm2020}/lib/date-parser.service.mjs +5 -5
  21. package/esm2020/lib/file-utils.mjs +35 -0
  22. package/{esm2022 → esm2020}/lib/get-channel-display-text.mjs +1 -1
  23. package/esm2020/lib/get-message-translation.mjs +12 -0
  24. package/esm2020/lib/icon/icon-placeholder/icon-placeholder.component.mjs +28 -0
  25. package/{esm2022 → esm2020}/lib/icon/icon.component.mjs +5 -5
  26. package/{esm2022 → esm2020}/lib/icon/icon.module.mjs +11 -11
  27. package/{esm2022 → esm2020}/lib/icon/loading-indicator/loading-indicator.component.mjs +5 -5
  28. package/esm2020/lib/icon/loading-indicator-placeholder/loading-indicator-placeholder.component.mjs +20 -0
  29. package/{esm2022 → esm2020}/lib/list-users.mjs +1 -1
  30. package/esm2020/lib/message/message.component.mjs +486 -0
  31. package/esm2020/lib/message-actions-box/message-actions-box.component.mjs +123 -0
  32. package/esm2020/lib/message-actions.service.mjs +187 -0
  33. package/esm2020/lib/message-bounce-prompt/message-bounce-prompt.component.mjs +71 -0
  34. package/esm2020/lib/message-input/autocomplete-textarea/autocomplete-textarea.component.mjs +333 -0
  35. package/{esm2022 → esm2020}/lib/message-input/emoji-input.service.mjs +7 -7
  36. package/esm2020/lib/message-input/message-input-config.service.mjs +50 -0
  37. package/esm2020/lib/message-input/message-input.component.mjs +507 -0
  38. package/{esm2022 → esm2020}/lib/message-input/textarea/textarea.component.mjs +6 -6
  39. package/{esm2022 → esm2020}/lib/message-input/textarea.directive.mjs +5 -5
  40. package/{esm2022 → esm2020}/lib/message-input/voice-recorder.service.mjs +5 -5
  41. package/{esm2022 → esm2020}/lib/message-list/group-styles.mjs +1 -1
  42. package/esm2020/lib/message-list/message-list.component.mjs +717 -0
  43. package/esm2020/lib/message-preview.mjs +21 -0
  44. package/esm2020/lib/message-reactions/message-reactions.component.mjs +168 -0
  45. package/esm2020/lib/message-reactions-selector/message-reactions-selector.component.mjs +61 -0
  46. package/{esm2022 → esm2020}/lib/message-reactions.service.mjs +6 -6
  47. package/esm2020/lib/message-text/message-text.component.mjs +143 -0
  48. package/esm2020/lib/message.service.mjs +43 -0
  49. package/{esm2022 → esm2020}/lib/modal/modal.component.mjs +6 -6
  50. package/esm2020/lib/notification/notification.component.mjs +20 -0
  51. package/esm2020/lib/notification-list/notification-list.component.mjs +36 -0
  52. package/{esm2022 → esm2020}/lib/notification.service.mjs +6 -6
  53. package/esm2020/lib/paginated-list/paginated-list.component.mjs +94 -0
  54. package/{esm2022 → esm2020}/lib/parse-date.mjs +1 -1
  55. package/esm2020/lib/read-by.mjs +12 -0
  56. package/esm2020/lib/stream-autocomplete-textarea.module.mjs +33 -0
  57. package/{esm2022 → esm2020}/lib/stream-avatar.module.mjs +5 -5
  58. package/{esm2022 → esm2020}/lib/stream-chat.module.mjs +59 -59
  59. package/{esm2022 → esm2020}/lib/stream-i18n.service.mjs +6 -6
  60. package/esm2020/lib/stream-textarea.module.mjs +31 -0
  61. package/{esm2022 → esm2020}/lib/theme.service.mjs +6 -6
  62. package/esm2020/lib/thread/thread.component.mjs +51 -0
  63. package/{esm2022 → esm2020}/lib/transliteration.service.mjs +5 -5
  64. package/esm2020/lib/types-custom.mjs +2 -0
  65. package/esm2020/lib/types.mjs +2 -0
  66. package/esm2020/lib/user-list/user-list.component.mjs +47 -0
  67. package/esm2020/lib/virtualized-list.service.mjs +271 -0
  68. package/{esm2022 → esm2020}/lib/virtualized-message-list.service.mjs +1 -1
  69. package/{esm2022 → esm2020}/lib/voice-recorder/amplitude-recorder.service.mjs +5 -5
  70. package/{esm2022 → esm2020}/lib/voice-recorder/audio-recorder.service.mjs +5 -5
  71. package/{esm2022 → esm2020}/lib/voice-recorder/media-recorder.mjs +1 -1
  72. package/esm2020/lib/voice-recorder/mp3-transcoder.mjs +61 -0
  73. package/esm2020/lib/voice-recorder/transcoder.service.mjs +121 -0
  74. package/esm2020/lib/voice-recorder/voice-recorder-wavebar/voice-recorder-wavebar.component.mjs +35 -0
  75. package/esm2020/lib/voice-recorder/voice-recorder.component.mjs +80 -0
  76. package/{esm2022 → esm2020}/lib/voice-recorder/voice-recorder.module.mjs +9 -9
  77. package/esm2020/lib/voice-recording/voice-recording-wavebar/voice-recording-wavebar.component.mjs +112 -0
  78. package/esm2020/lib/voice-recording/voice-recording.component.mjs +91 -0
  79. package/{esm2022 → esm2020}/lib/voice-recording/voice-recording.module.mjs +5 -5
  80. package/{esm2022 → esm2020}/lib/wave-form-sampler.mjs +1 -1
  81. package/esm2020/public-api.mjs +86 -0
  82. package/esm2020/stream-chat.mjs +2 -0
  83. package/fesm2015/stream-chat-angular.mjs +9171 -0
  84. package/fesm2015/stream-chat-angular.mjs.map +1 -0
  85. package/{fesm2022 → fesm2020}/stream-chat-angular.mjs +1251 -961
  86. package/fesm2020/stream-chat-angular.mjs.map +1 -0
  87. package/lib/attachment-configuration.service.d.ts +12 -12
  88. package/lib/attachment-list/attachment-list.component.d.ts +15 -10
  89. package/lib/attachment-preview-list/attachment-preview-list.component.d.ts +1 -1
  90. package/lib/attachment.service.d.ts +12 -10
  91. package/lib/avatar/avatar.component.d.ts +7 -7
  92. package/lib/avatar-placeholder/avatar-placeholder.component.d.ts +5 -5
  93. package/lib/channel/channel.component.d.ts +1 -1
  94. package/lib/channel-header/channel-header.component.d.ts +2 -2
  95. package/lib/channel-list/channel-list.component.d.ts +3 -4
  96. package/lib/channel-preview/channel-preview.component.d.ts +6 -6
  97. package/lib/channel-query.d.ts +26 -0
  98. package/lib/channel.service.d.ts +146 -154
  99. package/lib/chat-client.service.d.ts +17 -15
  100. package/lib/custom-templates.service.d.ts +50 -50
  101. package/lib/get-channel-display-text.d.ts +1 -2
  102. package/lib/get-message-translation.d.ts +3 -3
  103. package/lib/icon/icon-placeholder/icon-placeholder.component.d.ts +2 -2
  104. package/lib/icon/icon.component.d.ts +2 -2
  105. package/lib/icon/loading-indicator-placeholder/loading-indicator-placeholder.component.d.ts +1 -1
  106. package/lib/message/message.component.d.ts +6 -6
  107. package/lib/message-actions-box/message-actions-box.component.d.ts +5 -4
  108. package/lib/message-actions.service.d.ts +10 -10
  109. package/lib/message-bounce-prompt/message-bounce-prompt.component.d.ts +1 -1
  110. package/lib/message-input/autocomplete-textarea/autocomplete-textarea.component.d.ts +5 -5
  111. package/lib/message-input/emoji-input.service.d.ts +2 -2
  112. package/lib/message-input/message-input-config.service.d.ts +3 -3
  113. package/lib/message-input/message-input.component.d.ts +10 -33
  114. package/lib/message-input/textarea/textarea.component.d.ts +3 -3
  115. package/lib/message-input/textarea.directive.d.ts +1 -1
  116. package/lib/message-list/group-styles.d.ts +1 -1
  117. package/lib/message-list/message-list.component.d.ts +3 -2
  118. package/lib/message-preview.d.ts +2 -3
  119. package/lib/message-reactions/message-reactions.component.d.ts +9 -8
  120. package/lib/message-reactions-selector/message-reactions-selector.component.d.ts +6 -5
  121. package/lib/message-reactions.service.d.ts +4 -4
  122. package/lib/message-text/message-text.component.d.ts +5 -5
  123. package/lib/message.service.d.ts +6 -7
  124. package/lib/modal/modal.component.d.ts +1 -1
  125. package/lib/notification/notification.component.d.ts +2 -2
  126. package/lib/notification-list/notification-list.component.d.ts +1 -0
  127. package/lib/notification.service.d.ts +1 -1
  128. package/lib/paginated-list/paginated-list.component.d.ts +2 -5
  129. package/lib/read-by.d.ts +1 -2
  130. package/lib/stream-i18n.service.d.ts +1 -1
  131. package/lib/theme.service.d.ts +1 -1
  132. package/lib/thread/thread.component.d.ts +3 -3
  133. package/lib/types-custom.d.ts +15 -0
  134. package/lib/types.d.ts +116 -155
  135. package/lib/user-list/user-list.component.d.ts +2 -3
  136. package/lib/virtualized-message-list.service.d.ts +1 -1
  137. package/lib/voice-recorder/amplitude-recorder.service.d.ts +2 -2
  138. package/lib/voice-recorder/media-recorder.d.ts +2 -2
  139. package/lib/voice-recorder/transcoder.service.d.ts +4 -4
  140. package/lib/voice-recorder/voice-recorder-wavebar/voice-recorder-wavebar.component.d.ts +1 -0
  141. package/lib/voice-recorder/voice-recorder.component.d.ts +2 -2
  142. package/lib/voice-recording/voice-recording-wavebar/voice-recording-wavebar.component.d.ts +3 -3
  143. package/lib/voice-recording/voice-recording.component.d.ts +2 -3
  144. package/package.json +21 -15
  145. package/public-api.d.ts +3 -0
  146. package/src/assets/i18n/en.ts +0 -1
  147. package/src/assets/version.ts +1 -1
  148. package/esm2022/lib/attachment-configuration.service.mjs +0 -185
  149. package/esm2022/lib/attachment-list/attachment-list.component.mjs +0 -212
  150. package/esm2022/lib/attachment-preview-list/attachment-preview-list.component.mjs +0 -55
  151. package/esm2022/lib/attachment.service.mjs +0 -479
  152. package/esm2022/lib/avatar/avatar.component.mjs +0 -157
  153. package/esm2022/lib/avatar-placeholder/avatar-placeholder.component.mjs +0 -66
  154. package/esm2022/lib/channel/channel.component.mjs +0 -45
  155. package/esm2022/lib/channel-header/channel-header.component.mjs +0 -72
  156. package/esm2022/lib/channel-list/channel-list.component.mjs +0 -50
  157. package/esm2022/lib/channel-preview/channel-preview.component.mjs +0 -150
  158. package/esm2022/lib/channel.service.mjs +0 -1393
  159. package/esm2022/lib/chat-client.service.mjs +0 -227
  160. package/esm2022/lib/custom-templates.service.mjs +0 -244
  161. package/esm2022/lib/file-utils.mjs +0 -35
  162. package/esm2022/lib/get-message-translation.mjs +0 -12
  163. package/esm2022/lib/icon/icon-placeholder/icon-placeholder.component.mjs +0 -28
  164. package/esm2022/lib/icon/loading-indicator-placeholder/loading-indicator-placeholder.component.mjs +0 -20
  165. package/esm2022/lib/message/message.component.mjs +0 -486
  166. package/esm2022/lib/message-actions-box/message-actions-box.component.mjs +0 -120
  167. package/esm2022/lib/message-actions.service.mjs +0 -187
  168. package/esm2022/lib/message-bounce-prompt/message-bounce-prompt.component.mjs +0 -71
  169. package/esm2022/lib/message-input/autocomplete-textarea/autocomplete-textarea.component.mjs +0 -333
  170. package/esm2022/lib/message-input/message-input-config.service.mjs +0 -50
  171. package/esm2022/lib/message-input/message-input.component.mjs +0 -507
  172. package/esm2022/lib/message-list/message-list.component.mjs +0 -715
  173. package/esm2022/lib/message-preview.mjs +0 -21
  174. package/esm2022/lib/message-reactions/message-reactions.component.mjs +0 -165
  175. package/esm2022/lib/message-reactions-selector/message-reactions-selector.component.mjs +0 -57
  176. package/esm2022/lib/message-text/message-text.component.mjs +0 -143
  177. package/esm2022/lib/message.service.mjs +0 -43
  178. package/esm2022/lib/notification/notification.component.mjs +0 -20
  179. package/esm2022/lib/notification-list/notification-list.component.mjs +0 -33
  180. package/esm2022/lib/paginated-list/paginated-list.component.mjs +0 -94
  181. package/esm2022/lib/read-by.mjs +0 -12
  182. package/esm2022/lib/stream-autocomplete-textarea.module.mjs +0 -33
  183. package/esm2022/lib/stream-textarea.module.mjs +0 -31
  184. package/esm2022/lib/thread/thread.component.mjs +0 -51
  185. package/esm2022/lib/types.mjs +0 -2
  186. package/esm2022/lib/user-list/user-list.component.mjs +0 -47
  187. package/esm2022/lib/virtualized-list.service.mjs +0 -273
  188. package/esm2022/lib/voice-recorder/mp3-transcoder.mjs +0 -61
  189. package/esm2022/lib/voice-recorder/transcoder.service.mjs +0 -121
  190. package/esm2022/lib/voice-recorder/voice-recorder-wavebar/voice-recorder-wavebar.component.mjs +0 -32
  191. package/esm2022/lib/voice-recorder/voice-recorder.component.mjs +0 -80
  192. package/esm2022/lib/voice-recording/voice-recording-wavebar/voice-recording-wavebar.component.mjs +0 -112
  193. package/esm2022/lib/voice-recording/voice-recording.component.mjs +0 -91
  194. package/esm2022/public-api.mjs +0 -82
  195. package/fesm2022/stream-chat-angular.mjs.map +0 -1
  196. /package/{esm2022 → esm2020}/lib/format-duration.mjs +0 -0
  197. /package/{esm2022 → esm2020}/lib/injection-tokens.mjs +0 -0
  198. /package/{esm2022 → esm2020}/lib/is-image-attachment.mjs +0 -0
  199. /package/{esm2022 → esm2020}/lib/is-on-separate-date.mjs +0 -0
  200. /package/{esm2022 → esm2020}/lib/is-safari.mjs +0 -0
  201. /package/{esm2022 → esm2020}/lib/message-input/textarea.interface.mjs +0 -0
  202. /package/{esm2022 → esm2020}/stream-chat-angular.mjs +0 -0
@@ -1,479 +0,0 @@
1
- import { Injectable } from '@angular/core';
2
- import { createUriFromBlob, isImageFile } from './file-utils';
3
- import { BehaviorSubject, combineLatest, map, shareReplay, take, } from 'rxjs';
4
- import { isImageAttachment } from './is-image-attachment';
5
- import * as i0 from "@angular/core";
6
- import * as i1 from "./channel.service";
7
- import * as i2 from "./notification.service";
8
- import * as i3 from "./chat-client.service";
9
- import * as i4 from "./message.service";
10
- /**
11
- * The `AttachmentService` manages the uploads of a message input.
12
- *
13
- * You can read more about [uploads](/chat/docs/javascript/file_uploads/) in the Stream API documentation. You can use Stream's API or the dashboard to customize the [file](/chat/docs/javascript/app_setting_overview/#file-uploads) and [image upload](/chat/docs/javascript/app_setting_overview/#image-uploads) configuration.
14
- */
15
- export class AttachmentService {
16
- constructor(channelService, notificationService, chatClientService, messageService) {
17
- this.channelService = channelService;
18
- this.notificationService = notificationService;
19
- this.chatClientService = chatClientService;
20
- this.messageService = messageService;
21
- /**
22
- * Emits the number of uploads in progress.
23
- *
24
- * You can increment and decrement this counter if you're using custom attachments and want to disable message sending until all attachments are uploaded.
25
- *
26
- * The SDK will handle updating this counter for built-in attachments, but for custom attachments you should take care of this.
27
- */
28
- this.attachmentUploadInProgressCounter$ = new BehaviorSubject(0);
29
- /**
30
- * You can get and set the list if uploaded custom attachments
31
- *
32
- * By default the SDK components won't display these, but you can provide your own `customAttachmentPreviewListTemplate$` and `customAttachmentListTemplate$` for the [`CustomTemplatesService`](/chat/docs/sdk/angular/services/CustomTemplatesService/).
33
- */
34
- this.customAttachments$ = new BehaviorSubject([]);
35
- /**
36
- * The maximum number of attachments allowed for a message.
37
- *
38
- * The maximum is 30, you can set it to lower, but not higher.
39
- */
40
- this.maxNumberOfAttachments = 30;
41
- this.attachmentUploadsSubject = new BehaviorSubject([]);
42
- this.attachmentUploads$ = this.attachmentUploadsSubject.asObservable();
43
- this.chatClientService.appSettings$.subscribe((appSettings) => (this.appSettings = appSettings));
44
- this.attachmentsCounter$ = combineLatest([
45
- this.attachmentUploads$,
46
- this.customAttachments$,
47
- ]).pipe(map(([attchmentUploads, customAttachments]) => {
48
- return (attchmentUploads.filter((u) => u.state === 'success').length +
49
- customAttachments.length);
50
- }), shareReplay(1));
51
- this.attachmentsCounter$.subscribe((count) => {
52
- if (count > this.maxNumberOfAttachments) {
53
- this.attachmentLimitNotificationHide =
54
- this.notificationService.addPermanentNotification('streamChat.You currently have {{count}} attachments, the maximum is {{max}}', 'error', { count, max: this.maxNumberOfAttachments });
55
- }
56
- else {
57
- this.attachmentLimitNotificationHide?.();
58
- }
59
- });
60
- }
61
- /**
62
- * Resets the attachments uploads (for example after the message with the attachments sent successfully)
63
- */
64
- resetAttachmentUploads() {
65
- this.attachmentUploadsSubject.next([]);
66
- this.customAttachments$.next([]);
67
- this.attachmentLimitNotificationHide?.();
68
- }
69
- /**
70
- * Upload a voice recording
71
- * @param audioRecording
72
- * @returns A promise with true or false. If false is returned the upload was canceled because of a client side error. The error is emitted via the `NotificationService`.
73
- */
74
- async uploadVoiceRecording(audioRecording) {
75
- if (!this.isWithinLimit(1)) {
76
- return false;
77
- }
78
- if (!(await this.areAttachmentsHaveValidExtension([audioRecording.recording]))) {
79
- return false;
80
- }
81
- if (!(await this.areAttachmentsHaveValidSize([audioRecording.recording]))) {
82
- return false;
83
- }
84
- const upload = {
85
- file: audioRecording.recording,
86
- previewUri: audioRecording.asset_url,
87
- extraData: {
88
- duration: audioRecording.duration,
89
- waveform_data: audioRecording.waveform_data,
90
- },
91
- state: 'uploading',
92
- type: 'voiceRecording',
93
- };
94
- this.attachmentUploadsSubject.next([
95
- ...this.attachmentUploadsSubject.getValue(),
96
- upload,
97
- ]);
98
- await this.uploadAttachments([upload]);
99
- return true;
100
- }
101
- /**
102
- * Uploads the selected files, and creates preview for image files. The result is propagated throught the `attachmentUploads$` stream.
103
- * @param fileList The files selected by the user, if you have Blobs instead of Files, you can convert them with this method: https://developer.mozilla.org/en-US/docs/Web/API/File/File
104
- * @returns A promise with true or false. If false is returned the upload was canceled because of a client side error. The error is emitted via the `NotificationService`.
105
- */
106
- async filesSelected(fileList) {
107
- if (!fileList) {
108
- return;
109
- }
110
- const files = Array.from(fileList);
111
- if (!this.isWithinLimit(files.length)) {
112
- return false;
113
- }
114
- if (!(await this.areAttachmentsHaveValidExtension(files))) {
115
- return false;
116
- }
117
- if (!(await this.areAttachmentsHaveValidSize(files))) {
118
- return false;
119
- }
120
- const imageFiles = [];
121
- const dataFiles = [];
122
- const videoFiles = [];
123
- files.forEach((file) => {
124
- if (isImageFile(file)) {
125
- imageFiles.push(file);
126
- }
127
- else if (file.type.startsWith('video/')) {
128
- videoFiles.push(file);
129
- }
130
- else {
131
- dataFiles.push(file);
132
- }
133
- });
134
- imageFiles.forEach((f) => void this.createPreview(f));
135
- const newUploads = [
136
- ...imageFiles.map((file) => ({
137
- file,
138
- state: 'uploading',
139
- type: 'image',
140
- })),
141
- ...videoFiles.map((file) => ({
142
- file,
143
- state: 'uploading',
144
- type: 'video',
145
- })),
146
- ...dataFiles.map((file) => ({
147
- file,
148
- state: 'uploading',
149
- type: 'file',
150
- })),
151
- ];
152
- this.attachmentUploadsSubject.next([
153
- ...this.attachmentUploadsSubject.getValue(),
154
- ...newUploads,
155
- ]);
156
- await this.uploadAttachments(newUploads);
157
- return true;
158
- }
159
- /**
160
- * You can add custom `image`, `video` and `file` attachments using this method.
161
- *
162
- * Note: If you just want to use your own CDN for file uploads, you don't necessary need this method, you can just specify you own upload function in the [`ChannelService`](/chat/docs/sdk/angular/services/ChannelService/)
163
- * @param attachment
164
- */
165
- addAttachment(attachment) {
166
- attachment.isCustomAttachment = true;
167
- this.createFromAttachments([attachment]);
168
- }
169
- /**
170
- * Retries to upload an attachment.
171
- * @param file
172
- * @returns A promise with the result
173
- */
174
- async retryAttachmentUpload(file) {
175
- const attachmentUploads = this.attachmentUploadsSubject.getValue();
176
- const upload = attachmentUploads.find((u) => u.file === file);
177
- if (!upload) {
178
- return;
179
- }
180
- upload.state = 'uploading';
181
- this.attachmentUploadsSubject.next([...attachmentUploads]);
182
- await this.uploadAttachments([upload]);
183
- }
184
- /**
185
- * Deletes an attachment, the attachment can have any state (`error`, `uploading` or `success`).
186
- * @param upload
187
- */
188
- async deleteAttachment(upload) {
189
- const attachmentUploads = this.attachmentUploadsSubject.getValue();
190
- let result;
191
- if (upload.state === 'success' &&
192
- !upload.fromAttachment?.isCustomAttachment) {
193
- try {
194
- await this.channelService.deleteAttachment(upload);
195
- result = [...attachmentUploads];
196
- const index = attachmentUploads.indexOf(upload);
197
- result.splice(index, 1);
198
- }
199
- catch (error) {
200
- result = attachmentUploads;
201
- this.notificationService.addTemporaryNotification('streamChat.Error deleting attachment');
202
- }
203
- }
204
- else {
205
- result = [...attachmentUploads];
206
- const index = attachmentUploads.indexOf(upload);
207
- result.splice(index, 1);
208
- }
209
- this.attachmentUploadsSubject.next([...result]);
210
- }
211
- /**
212
- * Maps the current uploads to a format that can be sent along with the message to the Stream API.
213
- * @returns the attachments
214
- */
215
- mapToAttachments() {
216
- const attachmentUploads = this.attachmentUploadsSubject.getValue();
217
- const builtInAttachments = attachmentUploads
218
- .filter((r) => r.state === 'success')
219
- .map((r) => {
220
- let attachment = {
221
- type: r.type,
222
- };
223
- if (r.fromAttachment) {
224
- return r.fromAttachment;
225
- }
226
- else {
227
- attachment.mime_type = r.file?.type;
228
- if (r.type === 'image') {
229
- attachment.fallback = r.file?.name;
230
- attachment.image_url = r.url;
231
- }
232
- else {
233
- attachment.asset_url = r.url;
234
- attachment.title = r.file?.name;
235
- attachment.file_size = r.file?.size;
236
- attachment.thumb_url = r.thumb_url;
237
- }
238
- if (r.extraData) {
239
- attachment = { ...attachment, ...r.extraData };
240
- }
241
- }
242
- return attachment;
243
- });
244
- return [...builtInAttachments, ...this.customAttachments$.value];
245
- }
246
- /**
247
- * Maps attachments received from the Stream API to uploads. This is useful when editing a message.
248
- * @param attachments Attachemnts received with the message
249
- */
250
- createFromAttachments(attachments) {
251
- const attachmentUploads = [];
252
- const builtInAttachments = [];
253
- const customAttachments = [];
254
- attachments.forEach((attachment) => {
255
- if (this.messageService.isCustomAttachment(attachment)) {
256
- customAttachments.push(attachment);
257
- }
258
- else {
259
- builtInAttachments.push(attachment);
260
- }
261
- });
262
- builtInAttachments.forEach((attachment) => {
263
- if (isImageAttachment(attachment)) {
264
- attachmentUploads.push({
265
- url: (attachment.img_url ||
266
- attachment.thumb_url ||
267
- attachment.image_url),
268
- state: 'success',
269
- type: 'image',
270
- file: {
271
- name: attachment.fallback,
272
- type: attachment.mime_type,
273
- },
274
- fromAttachment: attachment,
275
- });
276
- }
277
- else if (attachment.type === 'file' || attachment.type === 'video') {
278
- attachmentUploads.push({
279
- url: attachment.asset_url,
280
- state: 'success',
281
- file: {
282
- name: attachment.title,
283
- size: attachment.file_size,
284
- type: attachment.mime_type,
285
- },
286
- type: attachment.type,
287
- thumb_url: attachment.thumb_url,
288
- fromAttachment: attachment,
289
- });
290
- }
291
- else if (attachment.type === 'voiceRecording') {
292
- attachmentUploads.push({
293
- url: attachment.asset_url,
294
- state: 'success',
295
- file: {
296
- name: attachment.title,
297
- size: attachment.file_size,
298
- type: attachment.mime_type,
299
- },
300
- type: 'voiceRecording',
301
- extraData: {
302
- duration: attachment.duration,
303
- waveform_data: attachment.waveform_data,
304
- },
305
- });
306
- }
307
- });
308
- if (attachmentUploads.length > 0) {
309
- this.attachmentUploadsSubject.next([
310
- ...this.attachmentUploadsSubject.getValue(),
311
- ...attachmentUploads,
312
- ]);
313
- }
314
- if (customAttachments.length > 0) {
315
- this.customAttachments$.next(customAttachments);
316
- }
317
- }
318
- async createPreview(file) {
319
- try {
320
- const uri = await createUriFromBlob(file);
321
- const attachmentUploads = this.attachmentUploadsSubject.getValue();
322
- const upload = attachmentUploads.find((upload) => upload.file === file);
323
- if (!upload) {
324
- return;
325
- }
326
- upload.previewUri = uri;
327
- this.attachmentUploadsSubject.next([...attachmentUploads]);
328
- }
329
- catch (e) {
330
- this.chatClientService?.chatClient?.logger('error', e instanceof Error ? e.message : `Can't create image preview`, { error: e, tag: ['AttachmentService'] });
331
- }
332
- }
333
- async uploadAttachments(uploads) {
334
- this.attachmentUploadInProgressCounter$.next(this.attachmentUploadInProgressCounter$.value + 1);
335
- const result = await this.channelService.uploadAttachments(uploads);
336
- const attachmentUploads = this.attachmentUploadsSubject.getValue();
337
- result.forEach((r) => {
338
- const upload = attachmentUploads.find((upload) => upload.file === r.file);
339
- if (!upload) {
340
- if (r.url) {
341
- void this.channelService.deleteAttachment(r);
342
- }
343
- return;
344
- }
345
- upload.state = r.state;
346
- upload.url = r.url;
347
- upload.thumb_url = r.thumb_url;
348
- if (upload.state === 'error') {
349
- upload.errorReason = r.errorReason;
350
- upload.errorExtraInfo = r.errorExtraInfo;
351
- let errorKey;
352
- const translateParams = { name: upload.file.name };
353
- switch (upload.errorReason) {
354
- case 'file-extension':
355
- errorKey =
356
- 'streamChat.Error uploading file, extension not supported';
357
- translateParams.ext = upload.errorExtraInfo?.[0]?.param;
358
- break;
359
- case 'file-size':
360
- errorKey =
361
- 'streamChat.Error uploading file, maximum file size exceeded';
362
- translateParams.limit = upload.errorExtraInfo?.[0]?.param;
363
- break;
364
- default:
365
- errorKey = 'streamChat.Error uploading file';
366
- }
367
- this.notificationService.addTemporaryNotification(errorKey, 'error', undefined, translateParams);
368
- }
369
- });
370
- this.attachmentUploadInProgressCounter$.next(this.attachmentUploadInProgressCounter$.value - 1);
371
- this.attachmentUploadsSubject.next([...attachmentUploads]);
372
- }
373
- async areAttachmentsHaveValidExtension(files) {
374
- if (!this.appSettings) {
375
- try {
376
- await this.chatClientService.getAppSettings();
377
- }
378
- catch (error) {
379
- return true;
380
- }
381
- }
382
- let isValid = true;
383
- files.forEach((f) => {
384
- let hasBlockedExtension;
385
- let hasBlockedMimeType;
386
- let hasNotAllowedExtension;
387
- let hasNotAllowedMimeType;
388
- if (isImageFile(f)) {
389
- hasBlockedExtension =
390
- !!this.appSettings?.image_upload_config?.blocked_file_extensions?.find((ext) => f.name.endsWith(ext));
391
- hasBlockedMimeType =
392
- !!this.appSettings?.image_upload_config?.blocked_mime_types?.find((type) => f.type === type);
393
- hasNotAllowedExtension =
394
- !!this.appSettings?.image_upload_config?.allowed_file_extensions
395
- ?.length &&
396
- !this.appSettings?.image_upload_config?.allowed_file_extensions?.find((ext) => f.name.endsWith(ext));
397
- hasNotAllowedMimeType =
398
- !!this.appSettings?.image_upload_config?.allowed_mime_types?.length &&
399
- !this.appSettings?.image_upload_config?.allowed_mime_types?.find((type) => f.type === type);
400
- }
401
- else {
402
- hasBlockedExtension =
403
- !!this.appSettings?.file_upload_config?.blocked_file_extensions?.find((ext) => f.name.endsWith(ext));
404
- hasBlockedMimeType =
405
- !!this.appSettings?.file_upload_config?.blocked_mime_types?.find((type) => f.type === type);
406
- hasNotAllowedExtension =
407
- !!this.appSettings?.file_upload_config?.allowed_file_extensions
408
- ?.length &&
409
- !this.appSettings?.file_upload_config?.allowed_file_extensions?.find((ext) => f.name.endsWith(ext));
410
- hasNotAllowedMimeType =
411
- !!this.appSettings?.file_upload_config?.allowed_mime_types?.length &&
412
- !this.appSettings?.file_upload_config?.allowed_mime_types?.find((type) => f.type === type);
413
- }
414
- if (hasBlockedExtension ||
415
- hasBlockedMimeType ||
416
- hasNotAllowedExtension ||
417
- hasNotAllowedMimeType) {
418
- this.notificationService.addTemporaryNotification('streamChat.Error uploading file, extension not supported', undefined, undefined, { name: f.name, ext: f.type });
419
- isValid = false;
420
- }
421
- });
422
- return isValid;
423
- }
424
- async areAttachmentsHaveValidSize(files) {
425
- if (!this.appSettings) {
426
- try {
427
- await this.chatClientService.getAppSettings();
428
- }
429
- catch (error) {
430
- return true;
431
- }
432
- }
433
- const imageSizeLimitInBytes = this.appSettings?.image_upload_config?.size_limit || 0;
434
- const imageSizeLimiString = `${imageSizeLimitInBytes / (1024 * 1024)}MB`;
435
- const fileSizeLimitInBytes = this.appSettings?.file_upload_config?.size_limit || 0;
436
- const fileSizeLimitInString = `${fileSizeLimitInBytes / (1024 * 1024)}MB`;
437
- let isValid = true;
438
- files.forEach((f) => {
439
- let isOverSized = false;
440
- let limit = '';
441
- if (isImageFile(f) && imageSizeLimitInBytes > 0) {
442
- isOverSized = f.size > imageSizeLimitInBytes;
443
- limit = imageSizeLimiString;
444
- }
445
- else if (fileSizeLimitInBytes > 0) {
446
- isOverSized = f.size > fileSizeLimitInBytes;
447
- limit = fileSizeLimitInString;
448
- }
449
- if (isOverSized) {
450
- this.notificationService.addTemporaryNotification('streamChat.Error uploading file, maximum file size exceeded', undefined, undefined, { name: f.name, limit: limit });
451
- isValid = false;
452
- }
453
- });
454
- return isValid;
455
- }
456
- isWithinLimit(numberOfNewAttachments) {
457
- let currentNumberOfAttachments = 0;
458
- this.attachmentsCounter$
459
- .pipe(take(1))
460
- .subscribe((counter) => (currentNumberOfAttachments = counter));
461
- if (currentNumberOfAttachments + numberOfNewAttachments >
462
- this.maxNumberOfAttachments) {
463
- this.notificationService.addTemporaryNotification(`streamChat.You can't uplod more than {{max}} attachments`, 'error', undefined, { max: this.maxNumberOfAttachments });
464
- return false;
465
- }
466
- else {
467
- return true;
468
- }
469
- }
470
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.0", ngImport: i0, type: AttachmentService, deps: [{ token: i1.ChannelService }, { token: i2.NotificationService }, { token: i3.ChatClientService }, { token: i4.MessageService }], target: i0.ɵɵFactoryTarget.Injectable }); }
471
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.0.0", ngImport: i0, type: AttachmentService, providedIn: 'root' }); }
472
- }
473
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0", ngImport: i0, type: AttachmentService, decorators: [{
474
- type: Injectable,
475
- args: [{
476
- providedIn: 'root',
477
- }]
478
- }], ctorParameters: () => [{ type: i1.ChannelService }, { type: i2.NotificationService }, { type: i3.ChatClientService }, { type: i4.MessageService }] });
479
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXR0YWNobWVudC5zZXJ2aWNlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vcHJvamVjdHMvc3RyZWFtLWNoYXQtYW5ndWxhci9zcmMvbGliL2F0dGFjaG1lbnQuc2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQzNDLE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxXQUFXLEVBQUUsTUFBTSxjQUFjLENBQUM7QUFDOUQsT0FBTyxFQUNMLGVBQWUsRUFDZixhQUFhLEVBQ2IsR0FBRyxFQUVILFdBQVcsRUFDWCxJQUFJLEdBQ0wsTUFBTSxNQUFNLENBQUM7QUFHZCxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSx1QkFBdUIsQ0FBQzs7Ozs7O0FBVTFEOzs7O0dBSUc7QUFJSCxNQUFNLE9BQU8saUJBQWlCO0lBcUM1QixZQUNVLGNBQThCLEVBQzlCLG1CQUF3QyxFQUN4QyxpQkFBb0MsRUFDcEMsY0FBOEI7UUFIOUIsbUJBQWMsR0FBZCxjQUFjLENBQWdCO1FBQzlCLHdCQUFtQixHQUFuQixtQkFBbUIsQ0FBcUI7UUFDeEMsc0JBQWlCLEdBQWpCLGlCQUFpQixDQUFtQjtRQUNwQyxtQkFBYyxHQUFkLGNBQWMsQ0FBZ0I7UUF0Q3hDOzs7Ozs7V0FNRztRQUNILHVDQUFrQyxHQUFHLElBQUksZUFBZSxDQUFTLENBQUMsQ0FBQyxDQUFDO1FBS3BFOzs7O1dBSUc7UUFDSCx1QkFBa0IsR0FBRyxJQUFJLGVBQWUsQ0FBa0IsRUFBRSxDQUFDLENBQUM7UUFLOUQ7Ozs7V0FJRztRQUNILDJCQUFzQixHQUFHLEVBQUUsQ0FBQztRQUNwQiw2QkFBd0IsR0FBRyxJQUFJLGVBQWUsQ0FDcEQsRUFBRSxDQUNILENBQUM7UUFVQSxJQUFJLENBQUMsa0JBQWtCLEdBQUcsSUFBSSxDQUFDLHdCQUF3QixDQUFDLFlBQVksRUFBRSxDQUFDO1FBQ3ZFLElBQUksQ0FBQyxp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b20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgY3JlYXRlVXJpRnJvbUJsb2IsIGlzSW1hZ2VGaWxlIH0gZnJvbSAnLi9maWxlLXV0aWxzJztcbmltcG9ydCB7XG4gIEJlaGF2aW9yU3ViamVjdCxcbiAgY29tYmluZUxhdGVzdCxcbiAgbWFwLFxuICBPYnNlcnZhYmxlLFxuICBzaGFyZVJlcGxheSxcbiAgdGFrZSxcbn0gZnJvbSAncnhqcyc7XG5pbXBvcnQgeyBBcHBTZXR0aW5ncywgQXR0YWNobWVudCB9IGZyb20gJ3N0cmVhbS1jaGF0JztcbmltcG9ydCB7IENoYW5uZWxTZXJ2aWNlIH0gZnJvbSAnLi9jaGFubmVsLnNlcnZpY2UnO1xuaW1wb3J0IHsgaXNJbWFnZUF0dGFjaG1lbnQgfSBmcm9tICcuL2lzLWltYWdlLWF0dGFjaG1lbnQnO1xuaW1wb3J0IHsgTm90aWZpY2F0aW9uU2VydmljZSB9IGZyb20gJy4vbm90aWZpY2F0aW9uLnNlcnZpY2UnO1xuaW1wb3J0IHtcbiAgQXR0YWNobWVudFVwbG9hZCxcbiAgQXVkaW9SZWNvcmRpbmcsXG4gIERlZmF1bHRTdHJlYW1DaGF0R2VuZXJpY3MsXG59IGZyb20gJy4vdHlwZXMnO1xuaW1wb3J0IHsgQ2hhdENsaWVudFNlcnZpY2UgfSBmcm9tICcuL2NoYXQtY2xpZW50LnNlcnZpY2UnO1xuaW1wb3J0IHsgTWVzc2FnZVNlcnZpY2UgfSBmcm9tICcuL21lc3NhZ2Uuc2VydmljZSc7XG5cbi8qKlxuICogVGhlIGBBdHRhY2htZW50U2VydmljZWAgbWFuYWdlcyB0aGUgdXBsb2FkcyBvZiBhIG1lc3NhZ2UgaW5wdXQuXG4gKlxuICogWW91IGNhbiByZWFkIG1vcmUgYWJvdXQgW3VwbG9hZHNdKC9jaGF0L2RvY3MvamF2YXNjcmlwdC9maWxlX3VwbG9hZHMvKSBpbiB0aGUgU3RyZWFtIEFQSSBkb2N1bWVudGF0aW9uLiBZb3UgY2FuIHVzZSBTdHJlYW0ncyBBUEkgb3IgdGhlIGRhc2hib2FyZCB0byBjdXN0b21pemUgdGhlIFtmaWxlXSgvY2hhdC9kb2NzL2phdmFzY3JpcHQvYXBwX3NldHRpbmdfb3ZlcnZpZXcvI2ZpbGUtdXBsb2FkcykgYW5kIFtpbWFnZSB1cGxvYWRdKC9jaGF0L2RvY3MvamF2YXNjcmlwdC9hcHBfc2V0dGluZ19vdmVydmlldy8jaW1hZ2UtdXBsb2FkcykgY29uZmlndXJhdGlvbi5cbiAqL1xuQEluamVjdGFibGUoe1xuICBwcm92aWRlZEluOiAncm9vdCcsXG59KVxuZXhwb3J0IGNsYXNzIEF0dGFjaG1lbnRTZXJ2aWNlPFxuICBUIGV4dGVuZHMgRGVmYXVsdFN0cmVhbUNoYXRHZW5lcmljcyA9IERlZmF1bHRTdHJlYW1DaGF0R2VuZXJpY3MsXG4+IHtcbiAgLyoqXG4gICAqIEVtaXRzIHRoZSBudW1iZXIgb2YgdXBsb2FkcyBpbiBwcm9ncmVzcy5cbiAgICpcbiAgICogWW91IGNhbiBpbmNyZW1lbnQgYW5kIGRlY3JlbWVudCB0aGlzIGNvdW50ZXIgaWYgeW91J3JlIHVzaW5nIGN1c3RvbSBhdHRhY2htZW50cyBhbmQgd2FudCB0byBkaXNhYmxlIG1lc3NhZ2Ugc2VuZGluZyB1bnRpbCBhbGwgYXR0YWNobWVudHMgYXJlIHVwbG9hZGVkLlxuICAgKlxuICAgKiBUaGUgU0RLIHdpbGwgaGFuZGxlIHVwZGF0aW5nIHRoaXMgY291bnRlciBmb3IgYnVpbHQtaW4gYXR0YWNobWVudHMsIGJ1dCBmb3IgY3VzdG9tIGF0dGFjaG1lbnRzIHlvdSBzaG91bGQgdGFrZSBjYXJlIG9mIHRoaXMuXG4gICAqL1xuICBhdHRhY2htZW50VXBsb2FkSW5Qcm9ncmVzc0NvdW50ZXIkID0gbmV3IEJlaGF2aW9yU3ViamVjdDxudW1iZXI+KDApO1xuICAvKipcbiAgICogRW1pdHMgdGhlIHN0YXRlIG9mIHRoZSB1cGxvYWRzIChbYEF0dGFjaG1lbnRVcGxvYWRbXWBdKGh0dHBzOi8vZ2l0aHViLmNvbS9HZXRTdHJlYW0vc3RyZWFtLWNoYXQtYW5ndWxhci9ibG9iL21hc3Rlci9wcm9qZWN0cy9zdHJlYW0tY2hhdC1hbmd1bGFyL3NyYy9saWIvdHlwZXMudHMpKSwgaXQgYWRkcyBhIHN0YXRlIChgc3VjY2Vzc2AsIGBlcnJvcmAgb3IgYHVwbG9hZGluZ2ApIHRvIGVhY2ggZmlsZSB0aGUgdXNlciBzZWxlY3RzIGZvciB1cGxvYWQuIEl0IGlzIHVzZWQgYnkgdGhlIFtgQXR0YWNobWVudFByZXZpZXdMaXN0YF0oL2NoYXQvZG9jcy9zZGsvYW5ndWxhci9jb21wb25lbnRzL0F0dGFjaG1lbnRQcmV2aWV3TGlzdENvbXBvbmVudC8pIHRvIGRpc3BsYXkgdGhlIGF0dGFjaG1lbnQgcHJldmlld3MuXG4gICAqL1xuICBhdHRhY2htZW50VXBsb2FkcyQ6IE9ic2VydmFibGU8QXR0YWNobWVudFVwbG9hZFtdPjtcbiAgLyoqXG4gICAqIFlvdSBjYW4gZ2V0IGFuZCBzZXQgdGhlIGxpc3QgaWYgdXBsb2FkZWQgY3VzdG9tIGF0dGFjaG1lbnRzXG4gICAqXG4gICAqIEJ5IGRlZmF1bHQgdGhlIFNESyBjb21wb25lbnRzIHdvbid0IGRpc3BsYXkgdGhlc2UsIGJ1dCB5b3UgY2FuIHByb3ZpZGUgeW91ciBvd24gYGN1c3RvbUF0dGFjaG1lbnRQcmV2aWV3TGlzdFRlbXBsYXRlJGAgYW5kIGBjdXN0b21BdHRhY2htZW50TGlzdFRlbXBsYXRlJGAgZm9yIHRoZSBbYEN1c3RvbVRlbXBsYXRlc1NlcnZpY2VgXSgvY2hhdC9kb2NzL3Nkay9hbmd1bGFyL3NlcnZpY2VzL0N1c3RvbVRlbXBsYXRlc1NlcnZpY2UvKS5cbiAgICovXG4gIGN1c3RvbUF0dGFjaG1lbnRzJCA9IG5ldyBCZWhhdmlvclN1YmplY3Q8QXR0YWNobWVudDxUPltdPihbXSk7XG4gIC8qKlxuICAgKiBUaGUgY3VycmVudCBudW1iZXIgb2YgYXR0YWNobWVudHNcbiAgICovXG4gIGF0dGFjaG1lbnRzQ291bnRlciQ6IE9ic2VydmFibGU8bnVtYmVyPjtcbiAgLyoqXG4gICAqIFRoZSBtYXhpbXVtIG51bWJlciBvZiBhdHRhY2htZW50cyBhbGxvd2VkIGZvciBhIG1lc3NhZ2UuXG4gICAqXG4gICAqIFRoZSBtYXhpbXVtIGlzIDMwLCB5b3UgY2FuIHNldCBpdCB0byBsb3dlciwgYnV0IG5vdCBoaWdoZXIuXG4gICAqL1xuICBtYXhOdW1iZXJPZkF0dGFjaG1lbnRzID0gMzA7XG4gIHByaXZhdGUgYXR0YWNobWVudFVwbG9hZHNTdWJqZWN0ID0gbmV3IEJlaGF2aW9yU3ViamVjdDxBdHRhY2htZW50VXBsb2FkW10+KFxuICAgIFtdLFxuICApO1xuICBwcml2YXRlIGFwcFNldHRpbmdzOiBBcHBTZXR0aW5ncyB8IHVuZGVmaW5lZDtcbiAgcHJpdmF0ZSBhdHRhY2htZW50TGltaXROb3RpZmljYXRpb25IaWRlPzogKCkgPT4gdm9pZDtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBwcml2YXRlIGNoYW5uZWxTZXJ2aWNlOiBDaGFubmVsU2VydmljZSxcbiAgICBwcml2YXRlIG5vdGlmaWNhdGlvblNlcnZpY2U6IE5vdGlmaWNhdGlvblNlcnZpY2UsXG4gICAgcHJpdmF0ZSBjaGF0Q2xpZW50U2VydmljZTogQ2hhdENsaWVudFNlcnZpY2UsXG4gICAgcHJpdmF0ZSBtZXNzYWdlU2VydmljZTogTWVzc2FnZVNlcnZpY2UsXG4gICkge1xuICAgIHRoaXMuYXR0YWNobWVudFVwbG9hZHMkID0gdGhpcy5hdHRhY2htZW50VXBsb2Fkc1N1YmplY3QuYXNPYnNlcnZhYmxlKCk7XG4gICAgdGhpcy5jaGF0Q2xpZW50U2VydmljZS5hcHBTZXR0aW5ncyQuc3Vic2NyaWJlKFxuICAgICAgKGFwcFNldHRpbmdzKSA9PiAodGhpcy5hcHBTZXR0aW5ncyA9IGFwcFNldHRpbmdzKSxcbiAgICApO1xuICAgIHRoaXMuYXR0YWNobWVudHNDb3VudGVyJCA9IGNvbWJpbmVMYXRlc3QoW1xuICAgICAgdGhpcy5hdHRhY2htZW50VXBsb2FkcyQsXG4gICAgICB0aGlzLmN1c3RvbUF0dGFjaG1lbnRzJCxcbiAgICBdKS5waXBlKFxuICAgICAgbWFwKChbYXR0Y2htZW50VXBsb2FkcywgY3VzdG9tQXR0YWNobWVudHNdKSA9PiB7XG4gICAgICAgIHJldHVybiAoXG4gICAgICAgICAgYXR0Y2htZW50VXBsb2Fkcy5maWx0ZXIoKHUpID0+IHUuc3RhdGUgPT09ICdzdWNjZXNzJykubGVuZ3RoICtcbiAgICAgICAgICBjdXN0b21BdHRhY2htZW50cy5sZW5ndGhcbiAgICAgICAgKTtcbiAgICAgIH0pLFxuICAgICAgc2hhcmVSZXBsYXkoMSksXG4gICAgKTtcbiAgICB0aGlzLmF0dGFjaG1lbnRzQ291bnRlciQuc3Vic2NyaWJlKChjb3VudCkgPT4ge1xuICAgICAgaWYgKGNvdW50ID4gdGhpcy5tYXhOdW1iZXJPZkF0dGFjaG1lbnRzKSB7XG4gICAgICAgIHRoaXMuYXR0YWNobWVudExpbWl0Tm90aWZpY2F0aW9uSGlkZSA9XG4gICAgICAgICAgdGhpcy5ub3RpZmljYXRpb25TZXJ2aWNlLmFkZFBlcm1hbmVudE5vdGlmaWNhdGlvbihcbiAgICAgICAgICAgICdzdHJlYW1DaGF0LllvdSBjdXJyZW50bHkgaGF2ZSB7e2NvdW50fX0gYXR0YWNobWVudHMsIHRoZSBtYXhpbXVtIGlzIHt7bWF4fX0nLFxuICAgICAgICAgICAgJ2Vycm9yJyxcbiAgICAgICAgICAgIHsgY291bnQsIG1heDogdGhpcy5tYXhOdW1iZXJPZkF0dGFjaG1lbnRzIH0sXG4gICAgICAgICAgKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRoaXMuYXR0YWNobWVudExpbWl0Tm90aWZpY2F0aW9uSGlkZT8uKCk7XG4gICAgICB9XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogUmVzZXRzIHRoZSBhdHRhY2htZW50cyB1cGxvYWRzIChmb3IgZXhhbXBsZSBhZnRlciB0aGUgbWVzc2FnZSB3aXRoIHRoZSBhdHRhY2htZW50cyBzZW50IHN1Y2Nlc3NmdWxseSlcbiAgICovXG4gIHJlc2V0QXR0YWNobWVudFVwbG9hZHMoKSB7XG4gICAgdGhpcy5hdHRhY2htZW50VXBsb2Fkc1N1YmplY3QubmV4dChbXSk7XG4gICAgdGhpcy5jdXN0b21BdHRhY2htZW50cyQubmV4dChbXSk7XG4gICAgdGhpcy5hdHRhY2htZW50TGltaXROb3RpZmljYXRpb25IaWRlPy4oKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBVcGxvYWQgYSB2b2ljZSByZWNvcmRpbmdcbiAgICogQHBhcmFtIGF1ZGlvUmVjb3JkaW5nXG4gICAqIEByZXR1cm5zIEEgcHJvbWlzZSB3aXRoIHRydWUgb3IgZmFsc2UuIElmIGZhbHNlIGlzIHJldHVybmVkIHRoZSB1cGxvYWQgd2FzIGNhbmNlbGVkIGJlY2F1c2Ugb2YgYSBjbGllbnQgc2lkZSBlcnJvci4gVGhlIGVycm9yIGlzIGVtaXR0ZWQgdmlhIHRoZSBgTm90aWZpY2F0aW9uU2VydmljZWAuXG4gICAqL1xuICBhc3luYyB1cGxvYWRWb2ljZVJlY29yZGluZyhhdWRpb1JlY29yZGluZzogQXVkaW9SZWNvcmRpbmcpIHtcbiAgICBpZiAoIXRoaXMuaXNXaXRoaW5MaW1pdCgxKSkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICBpZiAoXG4gICAgICAhKGF3YWl0IHRoaXMuYXJlQXR0YWNobWVudHNIYXZlVmFsaWRFeHRlbnNpb24oW2F1ZGlvUmVjb3JkaW5nLnJlY29yZGluZ10pKVxuICAgICkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICBpZiAoIShhd2FpdCB0aGlzLmFyZUF0dGFjaG1lbnRzSGF2ZVZhbGlkU2l6ZShbYXVkaW9SZWNvcmRpbmcucmVjb3JkaW5nXSkpKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgY29uc3QgdXBsb2FkID0ge1xuICAgICAgZmlsZTogYXVkaW9SZWNvcmRpbmcucmVjb3JkaW5nLFxuICAgICAgcHJldmlld1VyaTogYXVkaW9SZWNvcmRpbmcuYXNzZXRfdXJsLFxuICAgICAgZXh0cmFEYXRhOiB7XG4gICAgICAgIGR1cmF0aW9uOiBhdWRpb1JlY29yZGluZy5kdXJhdGlvbixcbiAgICAgICAgd2F2ZWZvcm1fZGF0YTogYXVkaW9SZWNvcmRpbmcud2F2ZWZvcm1fZGF0YSxcbiAgICAgIH0sXG4gICAgICBzdGF0ZTogJ3VwbG9hZGluZycgYXMgY29uc3QsXG4gICAgICB0eXBlOiAndm9pY2VSZWNvcmRpbmcnIGFzIGNvbnN0LFxuICAgIH07XG4gICAgdGhpcy5hdHRhY2htZW50VXBsb2Fkc1N1YmplY3QubmV4dChbXG4gICAgICAuLi50aGlzLmF0dGFjaG1lbnRVcGxvYWRzU3ViamVjdC5nZXRWYWx1ZSgpLFxuICAgICAgdXBsb2FkLFxuICAgIF0pO1xuICAgIGF3YWl0IHRoaXMudXBsb2FkQXR0YWNobWVudHMoW3VwbG9hZF0pO1xuICAgIHJldHVybiB0cnVlO1xuICB9XG5cbiAgLyoqXG4gICAqIFVwbG9hZHMgdGhlIHNlbGVjdGVkIGZpbGVzLCBhbmQgY3JlYXRlcyBwcmV2aWV3IGZvciBpbWFnZSBmaWxlcy4gVGhlIHJlc3VsdCBpcyBwcm9wYWdhdGVkIHRocm91Z2h0IHRoZSBgYXR0YWNobWVudFVwbG9hZHMkYCBzdHJlYW0uXG4gICAqIEBwYXJhbSBmaWxlTGlzdCBUaGUgZmlsZXMgc2VsZWN0ZWQgYnkgdGhlIHVzZXIsIGlmIHlvdSBoYXZlIEJsb2JzIGluc3RlYWQgb2YgRmlsZXMsIHlvdSBjYW4gY29udmVydCB0aGVtIHdpdGggdGhpcyBtZXRob2Q6IGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0FQSS9GaWxlL0ZpbGVcbiAgICogQHJldHVybnMgQSBwcm9taXNlIHdpdGggdHJ1ZSBvciBmYWxzZS4gSWYgZmFsc2UgaXMgcmV0dXJuZWQgdGhlIHVwbG9hZCB3YXMgY2FuY2VsZWQgYmVjYXVzZSBvZiBhIGNsaWVudCBzaWRlIGVycm9yLiBUaGUgZXJyb3IgaXMgZW1pdHRlZCB2aWEgdGhlIGBOb3RpZmljYXRpb25TZXJ2aWNlYC5cbiAgICovXG4gIGFzeW5jIGZpbGVzU2VsZWN0ZWQoZmlsZUxpc3Q6IEZpbGVMaXN0IHwgRmlsZVtdIHwgbnVsbCkge1xuICAgIGlmICghZmlsZUxpc3QpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zdCBmaWxlcyA9IEFycmF5LmZyb20oZmlsZUxpc3QpO1xuXG4gICAgaWYgKCF0aGlzLmlzV2l0aGluTGltaXQoZmlsZXMubGVuZ3RoKSkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIGlmICghKGF3YWl0IHRoaXMuYXJlQXR0YWNobWVudHNIYXZlVmFsaWRFeHRlbnNpb24oZmlsZXMpKSkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICBpZiAoIShhd2FpdCB0aGlzLmFyZUF0dGFjaG1lbnRzSGF2ZVZhbGlkU2l6ZShmaWxlcykpKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICAgIGNvbnN0IGltYWdlRmlsZXM6IEZpbGVbXSA9IFtdO1xuICAgIGNvbnN0IGRhdGFGaWxlczogRmlsZVtdID0gW107XG4gICAgY29uc3QgdmlkZW9GaWxlczogRmlsZVtdID0gW107XG5cbiAgICBmaWxlcy5mb3JFYWNoKChmaWxlKSA9PiB7XG4gICAgICBpZiAoaXNJbWFnZUZpbGUoZmlsZSkpIHtcbiAgICAgICAgaW1hZ2VGaWxlcy5wdXNoKGZpbGUpO1xuICAgICAgfSBlbHNlIGlmIChmaWxlLnR5cGUuc3RhcnRzV2l0aCgndmlkZW8vJykpIHtcbiAgICAgICAgdmlkZW9GaWxlcy5wdXNoKGZpbGUpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgZGF0YUZpbGVzLnB1c2goZmlsZSk7XG4gICAgICB9XG4gICAgfSk7XG4gICAgaW1hZ2VGaWxlcy5mb3JFYWNoKChmKSA9PiB2b2lkIHRoaXMuY3JlYXRlUHJldmlldyhmKSk7XG4gICAgY29uc3QgbmV3VXBsb2FkcyA9IFtcbiAgICAgIC4uLmltYWdlRmlsZXMubWFwKChmaWxlKSA9PiAoe1xuICAgICAgICBmaWxlLFxuICAgICAgICBzdGF0ZTogJ3VwbG9hZGluZycgYXMgY29uc3QsXG4gICAgICAgIHR5cGU6ICdpbWFnZScgYXMgY29uc3QsXG4gICAgICB9KSksXG4gICAgICAuLi52aWRlb0ZpbGVzLm1hcCgoZmlsZSkgPT4gKHtcbiAgICAgICAgZmlsZSxcbiAgICAgICAgc3RhdGU6ICd1cGxvYWRpbmcnIGFzIGNvbnN0LFxuICAgICAgICB0eXBlOiAndmlkZW8nIGFzIGNvbnN0LFxuICAgICAgfSkpLFxuICAgICAgLi4uZGF0YUZpbGVzLm1hcCgoZmlsZSkgPT4gKHtcbiAgICAgICAgZmlsZSxcbiAgICAgICAgc3RhdGU6ICd1cGxvYWRpbmcnIGFzIGNvbnN0LFxuICAgICAgICB0eXBlOiAnZmlsZScgYXMgY29uc3QsXG4gICAgICB9KSksXG4gICAgXTtcbiAgICB0aGlzLmF0dGFjaG1lbnRVcGxvYWRzU3ViamVjdC5uZXh0KFtcbiAgICAgIC4uLnRoaXMuYXR0YWNobWVudFVwbG9hZHNTdWJqZWN0LmdldFZhbHVlKCksXG4gICAgICAuLi5uZXdVcGxvYWRzLFxuICAgIF0pO1xuICAgIGF3YWl0IHRoaXMudXBsb2FkQXR0YWNobWVudHMobmV3VXBsb2Fkcyk7XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cblxuICAvKipcbiAgICogWW91IGNhbiBhZGQgY3VzdG9tIGBpbWFnZWAsIGB2aWRlb2AgYW5kIGBmaWxlYCBhdHRhY2htZW50cyB1c2luZyB0aGlzIG1ldGhvZC5cbiAgICpcbiAgICogTm90ZTogSWYgeW91IGp1c3Qgd2FudCB0byB1c2UgeW91ciBvd24gQ0ROIGZvciBmaWxlIHVwbG9hZHMsIHlvdSBkb24ndCBuZWNlc3NhcnkgbmVlZCB0aGlzIG1ldGhvZCwgeW91IGNhbiBqdXN0IHNwZWNpZnkgeW91IG93biB1cGxvYWQgZnVuY3Rpb24gaW4gdGhlIFtgQ2hhbm5lbFNlcnZpY2VgXSgvY2hhdC9kb2NzL3Nkay9hbmd1bGFyL3NlcnZpY2VzL0NoYW5uZWxTZXJ2aWNlLylcbiAgICogQHBhcmFtIGF0dGFjaG1lbnRcbiAgICovXG4gIGFkZEF0dGFjaG1lbnQoYXR0YWNobWVudDogQXR0YWNobWVudDxUPikge1xuICAgIGF0dGFjaG1lbnQuaXNDdXN0b21BdHRhY2htZW50ID0gdHJ1ZTtcbiAgICB0aGlzLmNyZWF0ZUZyb21BdHRhY2htZW50cyhbYXR0YWNobWVudF0pO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHJpZXMgdG8gdXBsb2FkIGFuIGF0dGFjaG1lbnQuXG4gICAqIEBwYXJhbSBmaWxlXG4gICAqIEByZXR1cm5zIEEgcHJvbWlzZSB3aXRoIHRoZSByZXN1bHRcbiAgICovXG4gIGFzeW5jIHJldHJ5QXR0YWNobWVudFVwbG9hZChmaWxlOiBGaWxlKSB7XG4gICAgY29uc3QgYXR0YWNobWVudFVwbG9hZHMgPSB0aGlzLmF0dGFjaG1lbnRVcGxvYWRzU3ViamVjdC5nZXRWYWx1ZSgpO1xuICAgIGNvbnN0IHVwbG9hZCA9IGF0dGFjaG1lbnRVcGxvYWRzLmZpbmQoKHUpID0+IHUuZmlsZSA9PT0gZmlsZSk7XG4gICAgaWYgKCF1cGxvYWQpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgdXBsb2FkLnN0YXRlID0gJ3VwbG9hZGluZyc7XG4gICAgdGhpcy5hdHRhY2htZW50VXBsb2Fkc1N1YmplY3QubmV4dChbLi4uYXR0YWNobWVudFVwbG9hZHNdKTtcbiAgICBhd2FpdCB0aGlzLnVwbG9hZEF0dGFjaG1lbnRzKFt1cGxvYWRdKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBEZWxldGVzIGFuIGF0dGFjaG1lbnQsIHRoZSBhdHRhY2htZW50IGNhbiBoYXZlIGFueSBzdGF0ZSAoYGVycm9yYCwgYHVwbG9hZGluZ2Agb3IgYHN1Y2Nlc3NgKS5cbiAgICogQHBhcmFtIHVwbG9hZFxuICAgKi9cbiAgYXN5bmMgZGVsZXRlQXR0YWNobWVudCh1cGxvYWQ6IEF0dGFjaG1lbnRVcGxvYWQpIHtcbiAgICBjb25zdCBhdHRhY2htZW50VXBsb2FkcyA9IHRoaXMuYXR0YWNobWVudFVwbG9hZHNTdWJqZWN0LmdldFZhbHVlKCk7XG4gICAgbGV0IHJlc3VsdCE6IEF0dGFjaG1lbnRVcGxvYWRbXTtcbiAgICBpZiAoXG4gICAgICB1cGxvYWQuc3RhdGUgPT09ICdzdWNjZXNzJyAmJlxuICAgICAgIXVwbG9hZC5mcm9tQXR0YWNobWVudD8uaXNDdXN0b21BdHRhY2htZW50XG4gICAgKSB7XG4gICAgICB0cnkge1xuICAgICAgICBhd2FpdCB0aGlzLmNoYW5uZWxTZXJ2aWNlLmRlbGV0ZUF0dGFjaG1lbnQodXBsb2FkKTtcbiAgICAgICAgcmVzdWx0ID0gWy4uLmF0dGFjaG1lbnRVcGxvYWRzXTtcbiAgICAgICAgY29uc3QgaW5kZXggPSBhdHRhY2htZW50VXBsb2Fkcy5pbmRleE9mKHVwbG9hZCk7XG4gICAgICAgIHJlc3VsdC5zcGxpY2UoaW5kZXgsIDEpO1xuICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgcmVzdWx0ID0gYXR0YWNobWVudFVwbG9hZHM7XG4gICAgICAgIHRoaXMubm90aWZpY2F0aW9uU2VydmljZS5hZGRUZW1wb3JhcnlOb3RpZmljYXRpb24oXG4gICAgICAgICAgJ3N0cmVhbUNoYXQuRXJyb3IgZGVsZXRpbmcgYXR0YWNobWVudCcsXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIHJlc3VsdCA9IFsuLi5hdHRhY2htZW50VXBsb2Fkc107XG4gICAgICBjb25zdCBpbmRleCA9IGF0dGFjaG1lbnRVcGxvYWRzLmluZGV4T2YodXBsb2FkKTtcbiAgICAgIHJlc3VsdC5zcGxpY2UoaW5kZXgsIDEpO1xuICAgIH1cbiAgICB0aGlzLmF0dGFjaG1lbnRVcGxvYWRzU3ViamVjdC5uZXh0KFsuLi5yZXN1bHRdKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBNYXBzIHRoZSBjdXJyZW50IHVwbG9hZHMgdG8gYSBmb3JtYXQgdGhhdCBjYW4gYmUgc2VudCBhbG9uZyB3aXRoIHRoZSBtZXNzYWdlIHRvIHRoZSBTdHJlYW0gQVBJLlxuICAgKiBAcmV0dXJucyB0aGUgYXR0YWNobWVudHNcbiAgICovXG4gIG1hcFRvQXR0YWNobWVudHMoKSB7XG4gICAgY29uc3QgYXR0YWNobWVudFVwbG9hZHMgPSB0aGlzLmF0dGFjaG1lbnRVcGxvYWRzU3ViamVjdC5nZXRWYWx1ZSgpO1xuICAgIGNvbnN0IGJ1aWx0SW5BdHRhY2htZW50cyA9IGF0dGFjaG1lbnRVcGxvYWRzXG4gICAgICAuZmlsdGVyKChyKSA9PiByLnN0YXRlID09PSAnc3VjY2VzcycpXG4gICAgICAubWFwKChyKSA9PiB7XG4gICAgICAgIGxldCBhdHRhY2htZW50OiBBdHRhY2htZW50ID0ge1xuICAgICAgICAgIHR5cGU6IHIudHlwZSxcbiAgICAgICAgfTtcbiAgICAgICAgaWYgKHIuZnJvbUF0dGFjaG1lbnQpIHtcbiAgICAgICAgICByZXR1cm4gci5mcm9tQXR0YWNobWVudDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBhdHRhY2htZW50Lm1pbWVfdHlwZSA9IHIuZmlsZT8udHlwZTtcbiAgICAgICAgICBpZiAoci50eXBlID09PSAnaW1hZ2UnKSB7XG4gICAgICAgICAgICBhdHRhY2htZW50LmZhbGxiYWNrID0gci5maWxlPy5uYW1lO1xuICAgICAgICAgICAgYXR0YWNobWVudC5pbWFnZV91cmwgPSByLnVybDtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgYXR0YWNobWVudC5hc3NldF91cmwgPSByLnVybDtcbiAgICAgICAgICAgIGF0dGFjaG1lbnQudGl0bGUgPSByLmZpbGU/Lm5hbWU7XG4gICAgICAgICAgICBhdHRhY2htZW50LmZpbGVfc2l6ZSA9IHIuZmlsZT8uc2l6ZTtcbiAgICAgICAgICAgIGF0dGFjaG1lbnQudGh1bWJfdXJsID0gci50aHVtYl91cmw7XG4gICAgICAgICAgfVxuICAgICAgICAgIGlmIChyLmV4dHJhRGF0YSkge1xuICAgICAgICAgICAgYXR0YWNobWVudCA9IHsgLi4uYXR0YWNobWVudCwgLi4uci5leHRyYURhdGEgfTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gYXR0YWNobWVudDtcbiAgICAgIH0pO1xuICAgIHJldHVybiBbLi4uYnVpbHRJbkF0dGFjaG1lbnRzLCAuLi50aGlzLmN1c3RvbUF0dGFjaG1lbnRzJC52YWx1ZV07XG4gIH1cblxuICAvKipcbiAgICogTWFwcyBhdHRhY2htZW50cyByZWNlaXZlZCBmcm9tIHRoZSBTdHJlYW0gQVBJIHRvIHVwbG9hZHMuIFRoaXMgaXMgdXNlZnVsIHdoZW4gZWRpdGluZyBhIG1lc3NhZ2UuXG4gICAqIEBwYXJhbSBhdHRhY2htZW50cyBBdHRhY2hlbW50cyByZWNlaXZlZCB3aXRoIHRoZSBtZXNzYWdlXG4gICAqL1xuICBjcmVhdGVGcm9tQXR0YWNobWVudHMoYXR0YWNobWVudHM6IEF0dGFjaG1lbnQ8VD5bXSkge1xuICAgIGNvbnN0IGF0dGFjaG1lbnRVcGxvYWRzOiBBdHRhY2htZW50VXBsb2FkW10gPSBbXTtcbiAgICBjb25zdCBidWlsdEluQXR0YWNobWVudHM6IEF0dGFjaG1lbnQ8VD5bXSA9IFtdO1xuICAgIGNvbnN0IGN1c3RvbUF0dGFjaG1lbnRzOiBBdHRhY2htZW50PFQ+W10gPSBbXTtcbiAgICBhdHRhY2htZW50cy5mb3JFYWNoKChhdHRhY2htZW50KSA9PiB7XG4gICAgICBpZiAodGhpcy5tZXNzYWdlU2VydmljZS5pc0N1c3RvbUF0dGFjaG1lbnQoYXR0YWNobWVudCkpIHtcbiAgICAgICAgY3VzdG9tQXR0YWNobWVudHMucHVzaChhdHRhY2htZW50KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGJ1aWx0SW5BdHRhY2htZW50cy5wdXNoKGF0dGFjaG1lbnQpO1xuICAgICAgfVxuICAgIH0pO1xuICAgIGJ1aWx0SW5BdHRhY2htZW50cy5mb3JFYWNoKChhdHRhY2htZW50KSA9PiB7XG4gICAgICBpZiAoaXNJbWFnZUF0dGFjaG1lbnQoYXR0YWNobWVudCkpIHtcbiAgICAgICAgYXR0YWNobWVudFVwbG9hZHMucHVzaCh7XG4gICAgICAgICAgdXJsOiAoYXR0YWNobWVudC5pbWdfdXJsIHx8XG4gICAgICAgICAgICBhdHRhY2htZW50LnRodW1iX3VybCB8fFxuICAgICAgICAgICAgYXR0YWNobWVudC5pbWFnZV91cmwpIGFzIHN0cmluZyxcbiAgICAgICAgICBzdGF0ZTogJ3N1Y2Nlc3MnLFxuICAgICAgICAgIHR5cGU6ICdpbWFnZScsXG4gICAgICAgICAgZmlsZToge1xuICAgICAgICAgICAgbmFtZTogYXR0YWNobWVudC5mYWxsYmFjayxcbiAgICAgICAgICAgIHR5cGU6IGF0dGFjaG1lbnQubWltZV90eXBlLFxuICAgICAgICAgIH0gYXMgRmlsZSxcbiAgICAgICAgICBmcm9tQXR0YWNobWVudDogYXR0YWNobWVudCxcbiAgICAgICAgfSk7XG4gICAgICB9IGVsc2UgaWYgKGF0dGFjaG1lbnQudHlwZSA9PT0gJ2ZpbGUnIHx8IGF0dGFjaG1lbnQudHlwZSA9PT0gJ3ZpZGVvJykge1xuICAgICAgICBhdHRhY2htZW50VXBsb2Fkcy5wdXNoKHtcbiAgICAgICAgICB1cmw6IGF0dGFjaG1lbnQuYXNzZXRfdXJsLFxuICAgICAgICAgIHN0YXRlOiAnc3VjY2VzcycsXG4gICAgICAgICAgZmlsZToge1xuICAgICAgICAgICAgbmFtZTogYXR0YWNobWVudC50aXRsZSxcbiAgICAgICAgICAgIHNpemU6IGF0dGFjaG1lbnQuZmlsZV9zaXplLFxuICAgICAgICAgICAgdHlwZTogYXR0YWNobWVudC5taW1lX3R5cGUsXG4gICAgICAgICAgfSBhcyBGaWxlLFxuICAgICAgICAgIHR5cGU6IGF0dGFjaG1lbnQudHlwZSxcbiAgICAgICAgICB0aHVtYl91cmw6IGF0dGFjaG1lbnQudGh1bWJfdXJsLFxuICAgICAgICAgIGZyb21BdHRhY2htZW50OiBhdHRhY2htZW50LFxuICAgICAgICB9KTtcbiAgICAgIH0gZWxzZSBpZiAoYXR0YWNobWVudC50eXBlID09PSAndm9pY2VSZWNvcmRpbmcnKSB7XG4gICAgICAgIGF0dGFjaG1lbnRVcGxvYWRzLnB1c2goe1xuICAgICAgICAgIHVybDogYXR0YWNobWVudC5hc3NldF91cmwsXG4gICAgICAgICAgc3RhdGU6ICdzdWNjZXNzJyxcbiAgICAgICAgICBmaWxlOiB7XG4gICAgICAgICAgICBuYW1lOiBhdHRhY2htZW50LnRpdGxlLFxuICAgICAgICAgICAgc2l6ZTogYXR0YWNobWVudC5maWxlX3NpemUsXG4gICAgICAgICAgICB0eXBlOiBhdHRhY2htZW50Lm1pbWVfdHlwZSxcbiAgICAgICAgICB9IGFzIEZpbGUsXG4gICAgICAgICAgdHlwZTogJ3ZvaWNlUmVjb3JkaW5nJyxcbiAgICAgICAgICBleHRyYURhdGE6IHtcbiAgICAgICAgICAgIGR1cmF0aW9uOiBhdHRhY2htZW50LmR1cmF0aW9uLFxuICAgICAgICAgICAgd2F2ZWZvcm1fZGF0YTogYXR0YWNobWVudC53YXZlZm9ybV9kYXRhLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH0pO1xuXG4gICAgaWYgKGF0dGFjaG1lbnRVcGxvYWRzLmxlbmd0aCA+IDApIHtcbiAgICAgIHRoaXMuYXR0YWNobWVudFVwbG9hZHNTdWJqZWN0Lm5leHQoW1xuICAgICAgICAuLi50aGlzLmF0dGFjaG1lbnRVcGxvYWRzU3ViamVjdC5nZXRWYWx1ZSgpLFxuICAgICAgICAuLi5hdHRhY2htZW50VXBsb2FkcyxcbiAgICAgIF0pO1xuICAgIH1cblxuICAgIGlmIChjdXN0b21BdHRhY2htZW50cy5sZW5ndGggPiAwKSB7XG4gICAgICB0aGlzLmN1c3RvbUF0dGFjaG1lbnRzJC5uZXh0KGN1c3RvbUF0dGFjaG1lbnRzKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGNyZWF0ZVByZXZpZXcoZmlsZTogRmlsZSB8IEJsb2IpIHtcbiAgICB0cnkge1xuICAgICAgY29uc3QgdXJpID0gYXdhaXQgY3JlYXRlVXJpRnJvbUJsb2IoZmlsZSk7XG4gICAgICBjb25zdCBhdHRhY2htZW50VXBsb2FkcyA9IHRoaXMuYXR0YWNobWVudFVwbG9hZHNTdWJqZWN0LmdldFZhbHVlKCk7XG4gICAgICBjb25zdCB1cGxvYWQgPSBhdHRhY2htZW50VXBsb2Fkcy5maW5kKCh1cGxvYWQpID0+IHVwbG9hZC5maWxlID09PSBmaWxlKTtcbiAgICAgIGlmICghdXBsb2FkKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICAgIHVwbG9hZC5wcmV2aWV3VXJpID0gdXJpO1xuICAgICAgdGhpcy5hdHRhY2htZW50VXBsb2Fkc1N1YmplY3QubmV4dChbLi4uYXR0YWNobWVudFVwbG9hZHNdKTtcbiAgICB9IGNhdGNoIChlOiB1bmtub3duKSB7XG4gICAgICB0aGlzLmNoYXRDbGllbnRTZXJ2aWNlPy5jaGF0Q2xpZW50Py5sb2dnZXIoXG4gICAgICAgICdlcnJvcicsXG4gICAgICAgIGUgaW5zdGFuY2VvZiBFcnJvciA/IGUubWVzc2FnZSA6IGBDYW4ndCBjcmVhdGUgaW1hZ2UgcHJldmlld2AsXG4gICAgICAgIHsgZXJyb3I6IGUsIHRhZzogWydBdHRhY2htZW50U2VydmljZSddIH0sXG4gICAgICApO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgdXBsb2FkQXR0YWNobWVudHModXBsb2FkczogQXR0YWNobWVudFVwbG9hZFtdKSB7XG4gICAgdGhpcy5hdHRhY2htZW50VXBsb2FkSW5Qcm9ncmVzc0NvdW50ZXIkLm5leHQoXG4gICAgICB0aGlzLmF0dGFjaG1lbnRVcGxvYWRJblByb2dyZXNzQ291bnRlciQudmFsdWUgKyAxLFxuICAgICk7XG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgdGhpcy5jaGFubmVsU2VydmljZS51cGxvYWRBdHRhY2htZW50cyh1cGxvYWRzKTtcbiAgICBjb25zdCBhdHRhY2htZW50VXBsb2FkcyA9IHRoaXMuYXR0YWNobWVudFVwbG9hZHNTdWJqZWN0LmdldFZhbHVlKCk7XG4gICAgcmVzdWx0LmZvckVhY2goKHIpID0+IHtcbiAgICAgIGNvbnN0IHVwbG9hZCA9IGF0dGFjaG1lbnRVcGxvYWRzLmZpbmQoKHVwbG9hZCkgPT4gdXBsb2FkLmZpbGUgPT09IHIuZmlsZSk7XG4gICAgICBpZiAoIXVwbG9hZCkge1xuICAgICAgICBpZiAoci51cmwpIHtcbiAgICAgICAgICB2b2lkIHRoaXMuY2hhbm5lbFNlcnZpY2UuZGVsZXRlQXR0YWNobWVudChyKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgICB1cGxvYWQuc3RhdGUgPSByLnN0YXRlO1xuICAgICAgdXBsb2FkLnVybCA9IHIudXJsO1xuICAgICAgdXBsb2FkLnRodW1iX3VybCA9IHIudGh1bWJfdXJsO1xuICAgICAgaWYgKHVwbG9hZC5zdGF0ZSA9PT0gJ2Vycm9yJykge1xuICAgICAgICB1cGxvYWQuZXJyb3JSZWFzb24gPSByLmVycm9yUmVhc29uO1xuICAgICAgICB1cGxvYWQuZXJyb3JFeHRyYUluZm8gPSByLmVycm9yRXh0cmFJbmZvO1xuICAgICAgICBsZXQgZXJyb3JLZXk7XG4gICAgICAgIGNvbnN0IHRyYW5zbGF0ZVBhcmFtczogeyBuYW1lOiBzdHJpbmc7IGV4dD86IHN0cmluZzsgbGltaXQ/OiBzdHJpbmcgfSA9XG4gICAgICAgICAgeyBuYW1lOiB1cGxvYWQuZmlsZS5uYW1lIH07XG4gICAgICAgIHN3aXRjaCAodXBsb2FkLmVycm9yUmVhc29uKSB7XG4gICAgICAgICAgY2FzZSAnZmlsZS1leHRlbnNpb24nOlxuICAgICAgICAgICAgZXJyb3JLZXkgPVxuICAgICAgICAgICAgICAnc3RyZWFtQ2hhdC5FcnJvciB1cGxvYWRpbmcgZmlsZSwgZXh0ZW5zaW9uIG5vdCBzdXBwb3J0ZWQnO1xuICAgICAgICAgICAgdHJhbnNsYXRlUGFyYW1zLmV4dCA9IHVwbG9hZC5lcnJvckV4dHJhSW5mbz8uWzBdPy5wYXJhbTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIGNhc2UgJ2ZpbGUtc2l6ZSc6XG4gICAgICAgICAgICBlcnJvcktleSA9XG4gICAgICAgICAgICAgICdzdHJlYW1DaGF0LkVycm9yIHVwbG9hZGluZyBmaWxlLCBtYXhpbXVtIGZpbGUgc2l6ZSBleGNlZWRlZCc7XG4gICAgICAgICAgICB0cmFuc2xhdGVQYXJhbXMubGltaXQgPSB1cGxvYWQuZXJyb3JFeHRyYUluZm8/LlswXT8ucGFyYW07XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgZXJyb3JLZXkgPSAnc3RyZWFtQ2hhdC5FcnJvciB1cGxvYWRpbmcgZmlsZSc7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5ub3RpZmljYXRpb25TZXJ2aWNlLmFkZFRlbXBvcmFyeU5vdGlmaWNhdGlvbihcbiAgICAgICAgICBlcnJvcktleSxcbiAgICAgICAgICAnZXJyb3InLFxuICAgICAgICAgIHVuZGVmaW5lZCxcbiAgICAgICAgICB0cmFuc2xhdGVQYXJhbXMsXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgfSk7XG4gICAgdGhpcy5hdHRhY2htZW50VXBsb2FkSW5Qcm9ncmVzc0NvdW50ZXIkLm5leHQoXG4gICAgICB0aGlzLmF0dGFjaG1lbnRVcGxvYWRJblByb2dyZXNzQ291bnRlciQudmFsdWUgLSAxLFxuICAgICk7XG4gICAgdGhpcy5hdHRhY2htZW50VXBsb2Fkc1N1YmplY3QubmV4dChbLi4uYXR0YWNobWVudFVwbG9hZHNdKTtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgYXJlQXR0YWNobWVudHNIYXZlVmFsaWRFeHRlbnNpb24oZmlsZXM6IEZpbGVbXSkge1xuICAgIGlmICghdGhpcy5hcHBTZXR0aW5ncykge1xuICAgICAgdHJ5IHtcbiAgICAgICAgYXdhaXQgdGhpcy5jaGF0Q2xpZW50U2VydmljZS5nZXRBcHBTZXR0aW5ncygpO1xuICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICB9XG4gICAgfVxuICAgIGxldCBpc1ZhbGlkID0gdHJ1ZTtcbiAgICBmaWxlcy5mb3JFYWNoKChmKSA9PiB7XG4gICAgICBsZXQgaGFzQmxvY2tlZEV4dGVuc2lvbjogYm9vbGVhbjtcbiAgICAgIGxldCBoYXNCbG9ja2VkTWltZVR5cGU6IGJvb2xlYW47XG4gICAgICBsZXQgaGFzTm90QWxsb3dlZEV4dGVuc2lvbjogYm9vbGVhbjtcbiAgICAgIGxldCBoYXNOb3RBbGxvd2VkTWltZVR5cGU6IGJvb2xlYW47XG4gICAgICBpZiAoaXNJbWFnZUZpbGUoZikpIHtcbiAgICAgICAgaGFzQmxvY2tlZEV4dGVuc2lvbiA9XG4gICAgICAgICAgISF0aGlzLmFwcFNldHRpbmdzPy5pbWFnZV91cGxvYWRfY29uZmlnPy5ibG9ja2VkX2ZpbGVfZXh0ZW5zaW9ucz8uZmluZChcbiAgICAgICAgICAgIChleHQpID0+IGYubmFtZS5lbmRzV2l0aChleHQpLFxuICAgICAgICAgICk7XG4gICAgICAgIGhhc0Jsb2NrZWRNaW1lVHlwZSA9XG4gICAgICAgICAgISF0aGlzLmFwcFNldHRpbmdzPy5pbWFnZV91cGxvYWRfY29uZmlnPy5ibG9ja2VkX21pbWVfdHlwZXM/LmZpbmQoXG4gICAgICAgICAgICAodHlwZSkgPT4gZi50eXBlID09PSB0eXBlLFxuICAgICAgICAgICk7XG4gICAgICAgIGhhc05vdEFsbG93ZWRFeHRlbnNpb24gPVxuICAgICAgICAgICEhdGhpcy5hcHBTZXR0aW5ncz8uaW1hZ2VfdXBsb2FkX2NvbmZpZz8uYWxsb3dlZF9maWxlX2V4dGVuc2lvbnNcbiAgICAgICAgICAgID8ubGVuZ3RoICYmXG4gICAgICAgICAgIXRoaXMuYXBwU2V0dGluZ3M/LmltYWdlX3VwbG9hZF9jb25maWc/LmFsbG93ZWRfZmlsZV9leHRlbnNpb25zPy5maW5kKFxuICAgICAgICAgICAgKGV4dCkgPT4gZi5uYW1lLmVuZHNXaXRoKGV4dCksXG4gICAgICAgICAgKTtcbiAgICAgICAgaGFzTm90QWxsb3dlZE1pbWVUeXBlID1cbiAgICAgICAgICAhIXRoaXMuYXBwU2V0dGluZ3M/LmltYWdlX3VwbG9hZF9jb25maWc/LmFsbG93ZWRfbWltZV90eXBlcz8ubGVuZ3RoICYmXG4gICAgICAgICAgIXRoaXMuYXBwU2V0dGluZ3M/LmltYWdlX3VwbG9hZF9jb25maWc/LmFsbG93ZWRfbWltZV90eXBlcz8uZmluZChcbiAgICAgICAgICAgICh0eXBlKSA9PiBmLnR5cGUgPT09IHR5cGUsXG4gICAgICAgICAgKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGhhc0Jsb2NrZWRFeHRlbnNpb24gPVxuICAgICAgICAgICEhdGhpcy5hcHBTZXR0aW5ncz8uZmlsZV91cGxvYWRfY29uZmlnPy5ibG9ja2VkX2ZpbGVfZXh0ZW5zaW9ucz8uZmluZChcbiAgICAgICAgICAgIChleHQpID0+IGYubmFtZS5lbmRzV2l0aChleHQpLFxuICAgICAgICAgICk7XG4gICAgICAgIGhhc0Jsb2NrZWRNaW1lVHlwZSA9XG4gICAgICAgICAgISF0aGlzLmFwcFNldHRpbmdzPy5maWxlX3VwbG9hZF9jb25maWc/LmJsb2NrZWRfbWltZV90eXBlcz8uZmluZChcbiAgICAgICAgICAgICh0eXBlKSA9PiBmLnR5cGUgPT09IHR5cGUsXG4gICAgICAgICAgKTtcbiAgICAgICAgaGFzTm90QWxsb3dlZEV4dGVuc2lvbiA9XG4gICAgICAgICAgISF0aGlzLmFwcFNldHRpbmdzPy5maWxlX3VwbG9hZF9jb25maWc/LmFsbG93ZWRfZmlsZV9leHRlbnNpb25zXG4gICAgICAgICAgICA/Lmxlbmd0aCAmJlxuICAgICAgICAgICF0aGlzLmFwcFNldHRpbmdzPy5maWxlX3VwbG9hZF9jb25maWc/LmFsbG93ZWRfZmlsZV9leHRlbnNpb25zPy5maW5kKFxuICAgICAgICAgICAgKGV4dCkgPT4gZi5uYW1lLmVuZHNXaXRoKGV4dCksXG4gICAgICAgICAgKTtcbiAgICAgICAgaGFzTm90QWxsb3dlZE1pbWVUeXBlID1cbiAgICAgICAgICAhIXRoaXMuYXBwU2V0dGluZ3M/LmZpbGVfdXBsb2FkX2NvbmZpZz8uYWxsb3dlZF9taW1lX3R5cGVzPy5sZW5ndGggJiZcbiAgICAgICAgICAhdGhpcy5hcHBTZXR0aW5ncz8uZmlsZV91cGxvYWRfY29uZmlnPy5hbGxvd2VkX21pbWVfdHlwZXM/LmZpbmQoXG4gICAgICAgICAgICAodHlwZSkgPT4gZi50eXBlID09PSB0eXBlLFxuICAgICAgICAgICk7XG4gICAgICB9XG4gICAgICBpZiAoXG4gICAgICAgIGhhc0Jsb2NrZWRFeHRlbnNpb24gfHxcbiAgICAgICAgaGFzQmxvY2tlZE1pbWVUeXBlIHx8XG4gICAgICAgIGhhc05vdEFsbG93ZWRFeHRlbnNpb24gfHxcbiAgICAgICAgaGFzTm90QWxsb3dlZE1pbWVUeXBlXG4gICAgICApIHtcbiAgICAgICAgdGhpcy5ub3RpZmljYXRpb25TZXJ2aWNlLmFkZFRlbXBvcmFyeU5vdGlmaWNhdGlvbihcbiAgICAgICAgICAnc3RyZWFtQ2hhdC5FcnJvciB1cGxvYWRpbmcgZmlsZSwgZXh0ZW5zaW9uIG5vdCBzdXBwb3J0ZWQnLFxuICAgICAgICAgIHVuZGVmaW5lZCxcbiAgICAgICAgICB1bmRlZmluZWQsXG4gICAgICAgICAgeyBuYW1lOiBmLm5hbWUsIGV4dDogZi50eXBlIH0sXG4gICAgICAgICk7XG4gICAgICAgIGlzVmFsaWQgPSBmYWxzZTtcbiAgICAgIH1cbiAgICB9KTtcbiAgICByZXR1cm4gaXNWYWxpZDtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgYXJlQXR0YWNobWVudHNIYXZlVmFsaWRTaXplKGZpbGVzOiBGaWxlW10pIHtcbiAgICBpZiAoIXRoaXMuYXBwU2V0dGluZ3MpIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIGF3YWl0IHRoaXMuY2hhdENsaWVudFNlcnZpY2UuZ2V0QXBwU2V0dGluZ3MoKTtcbiAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgfVxuICAgIH1cbiAgICBjb25zdCBpbWFnZVNpemVMaW1pdEluQnl0ZXMgPVxuICAgICAgdGhpcy5hcHBTZXR0aW5ncz8uaW1hZ2VfdXBsb2FkX2NvbmZpZz8uc2l6ZV9saW1pdCB8fCAwO1xuICAgIGNvbnN0IGltYWdlU2l6ZUxpbWlTdHJpbmcgPSBgJHtpbWFnZVNpemVMaW1pdEluQnl0ZXMgLyAoMTAyNCAqIDEwMjQpfU1CYDtcbiAgICBjb25zdCBmaWxlU2l6ZUxpbWl0SW5CeXRlcyA9XG4gICAgICB0aGlzLmFwcFNldHRpbmdzPy5maWxlX3VwbG9hZF9jb25maWc/LnNpemVfbGltaXQgfHwgMDtcbiAgICBjb25zdCBmaWxlU2l6ZUxpbWl0SW5TdHJpbmcgPSBgJHtmaWxlU2l6ZUxpbWl0SW5CeXRlcyAvICgxMDI0ICogMTAyNCl9TUJgO1xuICAgIGxldCBpc1ZhbGlkID0gdHJ1ZTtcbiAgICBmaWxlcy5mb3JFYWNoKChmKSA9PiB7XG4gICAgICBsZXQgaXNPdmVyU2l6ZWQgPSBmYWxzZTtcbiAgICAgIGxldCBsaW1pdCA9ICcnO1xuICAgICAgaWYgKGlzSW1hZ2VGaWxlKGYpICYmIGltYWdlU2l6ZUxpbWl0SW5CeXRlcyA+IDApIHtcbiAgICAgICAgaXNPdmVyU2l6ZWQgPSBmLnNpemUgPiBpbWFnZVNpemVMaW1pdEluQnl0ZXM7XG4gICAgICAgIGxpbWl0ID0gaW1hZ2VTaXplTGltaVN0cmluZztcbiAgICAgIH0gZWxzZSBpZiAoZmlsZVNpemVMaW1pdEluQnl0ZXMgPiAwKSB7XG4gICAgICAgIGlzT3ZlclNpemVkID0gZi5zaXplID4gZmlsZVNpemVMaW1pdEluQnl0ZXM7XG4gICAgICAgIGxpbWl0ID0gZmlsZVNpemVMaW1pdEluU3RyaW5nO1xuICAgICAgfVxuICAgICAgaWYgKGlzT3ZlclNpemVkKSB7XG4gICAgICAgIHRoaXMubm90aWZpY2F0aW9uU2VydmljZS5hZGRUZW1wb3JhcnlOb3RpZmljYXRpb24oXG4gICAgICAgICAgJ3N0cmVhbUNoYXQuRXJyb3IgdXBsb2FkaW5nIGZpbGUsIG1heGltdW0gZmlsZSBzaXplIGV4Y2VlZGVkJyxcbiAgICAgICAgICB1bmRlZmluZWQsXG4gICAgICAgICAgdW5kZWZpbmVkLFxuICAgICAgICAgIHsgbmFtZTogZi5uYW1lLCBsaW1pdDogbGltaXQgfSxcbiAgICAgICAgKTtcbiAgICAgICAgaXNWYWxpZCA9IGZhbHNlO1xuICAgICAgfVxuICAgIH0pO1xuICAgIHJldHVybiBpc1ZhbGlkO1xuICB9XG5cbiAgcHJpdmF0ZSBpc1dpdGhpbkxpbWl0KG51bWJlck9mTmV3QXR0YWNobWVudHM6IG51bWJlcikge1xuICAgIGxldCBjdXJyZW50TnVtYmVyT2ZBdHRhY2htZW50czogbnVtYmVyID0gMDtcbiAgICB0aGlzLmF0dGFjaG1lbnRzQ291bnRlciRcbiAgICAgIC5waXBlKHRha2UoMSkpXG4gICAgICAuc3Vic2NyaWJlKChjb3VudGVyKSA9PiAoY3VycmVudE51bWJlck9mQXR0YWNobWVudHMgPSBjb3VudGVyKSk7XG4gICAgaWYgKFxuICAgICAgY3VycmVudE51bWJlck9mQXR0YWNobWVudHMgKyBudW1iZXJPZk5ld0F0dGFjaG1lbnRzID5cbiAgICAgIHRoaXMubWF4TnVtYmVyT2ZBdHRhY2htZW50c1xuICAgICkge1xuICAgICAgdGhpcy5ub3RpZmljYXRpb25TZXJ2aWNlLmFkZFRlbXBvcmFyeU5vdGlmaWNhdGlvbihcbiAgICAgICAgYHN0cmVhbUNoYXQuWW91IGNhbid0IHVwbG9kIG1vcmUgdGhhbiB7e21heH19IGF0dGFjaG1lbnRzYCxcbiAgICAgICAgJ2Vycm9yJyxcbiAgICAgICAgdW5kZWZpbmVkLFxuICAgICAgICB7IG1heDogdGhpcy5tYXhOdW1iZXJPZkF0dGFjaG1lbnRzIH0sXG4gICAgICApO1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gIH1cbn1cbiJdfQ==