stream-chat-angular 5.13.0 → 6.0.0-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (165) hide show
  1. package/assets/i18n/en.d.ts +1 -0
  2. package/assets/version.d.ts +1 -1
  3. package/{esm2020 → esm2022}/assets/i18n/en.mjs +2 -1
  4. package/{esm2020 → esm2022}/assets/version.mjs +2 -2
  5. package/{esm2020 → esm2022}/lib/attachment-configuration.service.mjs +4 -4
  6. package/esm2022/lib/attachment-list/attachment-list.component.mjs +212 -0
  7. package/esm2022/lib/attachment-preview-list/attachment-preview-list.component.mjs +55 -0
  8. package/{esm2020 → esm2022}/lib/attachment.service.mjs +5 -5
  9. package/esm2022/lib/avatar/avatar.component.mjs +157 -0
  10. package/{esm2020 → esm2022}/lib/avatar-placeholder/avatar-placeholder.component.mjs +6 -6
  11. package/esm2022/lib/channel/channel.component.mjs +45 -0
  12. package/esm2022/lib/channel-header/channel-header.component.mjs +72 -0
  13. package/esm2022/lib/channel-list/channel-list.component.mjs +50 -0
  14. package/esm2022/lib/channel-preview/channel-preview.component.mjs +150 -0
  15. package/esm2022/lib/channel.service.mjs +1381 -0
  16. package/esm2022/lib/chat-client.service.mjs +227 -0
  17. package/{esm2020 → esm2022}/lib/custom-templates.service.mjs +5 -5
  18. package/{esm2020 → esm2022}/lib/date-parser.service.mjs +5 -5
  19. package/esm2022/lib/file-utils.mjs +35 -0
  20. package/{esm2020 → esm2022}/lib/get-channel-display-text.mjs +1 -1
  21. package/{esm2020 → esm2022}/lib/get-message-translation.mjs +1 -1
  22. package/{esm2020 → esm2022}/lib/icon/icon-placeholder/icon-placeholder.component.mjs +6 -6
  23. package/{esm2020 → esm2022}/lib/icon/icon.component.mjs +5 -5
  24. package/{esm2020 → esm2022}/lib/icon/icon.module.mjs +11 -11
  25. package/{esm2020 → esm2022}/lib/icon/loading-indicator/loading-indicator.component.mjs +5 -5
  26. package/{esm2020 → esm2022}/lib/icon/loading-indicator-placeholder/loading-indicator-placeholder.component.mjs +6 -6
  27. package/{esm2020 → esm2022}/lib/list-users.mjs +1 -1
  28. package/esm2022/lib/message/message.component.mjs +486 -0
  29. package/esm2022/lib/message-actions-box/message-actions-box.component.mjs +120 -0
  30. package/{esm2020 → esm2022}/lib/message-actions.service.mjs +5 -5
  31. package/esm2022/lib/message-bounce-prompt/message-bounce-prompt.component.mjs +71 -0
  32. package/{esm2020 → esm2022}/lib/message-input/autocomplete-textarea/autocomplete-textarea.component.mjs +6 -6
  33. package/{esm2020 → esm2022}/lib/message-input/emoji-input.service.mjs +5 -5
  34. package/{esm2020 → esm2022}/lib/message-input/message-input-config.service.mjs +5 -5
  35. package/esm2022/lib/message-input/message-input.component.mjs +507 -0
  36. package/{esm2020 → esm2022}/lib/message-input/textarea/textarea.component.mjs +5 -5
  37. package/{esm2020 → esm2022}/lib/message-input/textarea.directive.mjs +5 -5
  38. package/{esm2020 → esm2022}/lib/message-input/voice-recorder.service.mjs +5 -5
  39. package/{esm2020 → esm2022}/lib/message-list/group-styles.mjs +1 -1
  40. package/esm2022/lib/message-list/message-list.component.mjs +715 -0
  41. package/{esm2020 → esm2022}/lib/message-preview.mjs +1 -1
  42. package/esm2022/lib/message-reactions/message-reactions.component.mjs +165 -0
  43. package/esm2022/lib/message-reactions-selector/message-reactions-selector.component.mjs +57 -0
  44. package/{esm2020 → esm2022}/lib/message-reactions.service.mjs +5 -5
  45. package/{esm2020 → esm2022}/lib/message-text/message-text.component.mjs +6 -6
  46. package/esm2022/lib/message.service.mjs +43 -0
  47. package/{esm2020 → esm2022}/lib/modal/modal.component.mjs +6 -6
  48. package/{esm2020 → esm2022}/lib/notification/notification.component.mjs +6 -6
  49. package/esm2022/lib/notification-list/notification-list.component.mjs +33 -0
  50. package/{esm2020 → esm2022}/lib/notification.service.mjs +5 -5
  51. package/esm2022/lib/paginated-list/paginated-list.component.mjs +94 -0
  52. package/{esm2020 → esm2022}/lib/parse-date.mjs +1 -1
  53. package/{esm2020 → esm2022}/lib/read-by.mjs +1 -1
  54. package/esm2022/lib/stream-autocomplete-textarea.module.mjs +33 -0
  55. package/{esm2020 → esm2022}/lib/stream-avatar.module.mjs +5 -5
  56. package/{esm2020 → esm2022}/lib/stream-chat.module.mjs +59 -59
  57. package/{esm2020 → esm2022}/lib/stream-i18n.service.mjs +5 -5
  58. package/esm2022/lib/stream-textarea.module.mjs +31 -0
  59. package/{esm2020 → esm2022}/lib/theme.service.mjs +5 -5
  60. package/{esm2020 → esm2022}/lib/thread/thread.component.mjs +6 -6
  61. package/{esm2020 → esm2022}/lib/transliteration.service.mjs +5 -5
  62. package/esm2022/lib/types.mjs +2 -0
  63. package/{esm2020 → esm2022}/lib/user-list/user-list.component.mjs +5 -5
  64. package/esm2022/lib/virtualized-list.service.mjs +273 -0
  65. package/{esm2020 → esm2022}/lib/virtualized-message-list.service.mjs +1 -1
  66. package/{esm2020 → esm2022}/lib/voice-recorder/amplitude-recorder.service.mjs +5 -5
  67. package/{esm2020 → esm2022}/lib/voice-recorder/audio-recorder.service.mjs +5 -5
  68. package/{esm2020 → esm2022}/lib/voice-recorder/media-recorder.mjs +1 -1
  69. package/esm2022/lib/voice-recorder/mp3-transcoder.mjs +61 -0
  70. package/esm2022/lib/voice-recorder/transcoder.service.mjs +121 -0
  71. package/esm2022/lib/voice-recorder/voice-recorder-wavebar/voice-recorder-wavebar.component.mjs +32 -0
  72. package/esm2022/lib/voice-recorder/voice-recorder.component.mjs +80 -0
  73. package/{esm2020 → esm2022}/lib/voice-recorder/voice-recorder.module.mjs +9 -9
  74. package/esm2022/lib/voice-recording/voice-recording-wavebar/voice-recording-wavebar.component.mjs +112 -0
  75. package/esm2022/lib/voice-recording/voice-recording.component.mjs +91 -0
  76. package/{esm2020 → esm2022}/lib/voice-recording/voice-recording.module.mjs +5 -5
  77. package/{esm2020 → esm2022}/lib/wave-form-sampler.mjs +1 -1
  78. package/esm2022/public-api.mjs +82 -0
  79. package/{fesm2020 → fesm2022}/stream-chat-angular.mjs +857 -1140
  80. package/fesm2022/stream-chat-angular.mjs.map +1 -0
  81. package/lib/attachment-list/attachment-list.component.d.ts +2 -5
  82. package/lib/attachment-preview-list/attachment-preview-list.component.d.ts +2 -2
  83. package/lib/attachment.service.d.ts +1 -1
  84. package/lib/avatar/avatar.component.d.ts +4 -4
  85. package/lib/avatar-placeholder/avatar-placeholder.component.d.ts +1 -1
  86. package/lib/channel-list/channel-list.component.d.ts +1 -0
  87. package/lib/channel-preview/channel-preview.component.d.ts +3 -4
  88. package/lib/channel.service.d.ts +40 -106
  89. package/lib/chat-client.service.d.ts +1 -4
  90. package/lib/custom-templates.service.d.ts +10 -10
  91. package/lib/icon/icon-placeholder/icon-placeholder.component.d.ts +1 -1
  92. package/lib/icon/icon.component.d.ts +2 -2
  93. package/lib/message/message.component.d.ts +2 -2
  94. package/lib/message-actions-box/message-actions-box.component.d.ts +2 -3
  95. package/lib/message-actions.service.d.ts +1 -1
  96. package/lib/message-input/autocomplete-textarea/autocomplete-textarea.component.d.ts +2 -2
  97. package/lib/message-input/message-input.component.d.ts +2 -2
  98. package/lib/message-input/textarea/textarea.component.d.ts +1 -1
  99. package/lib/message-input/textarea.directive.d.ts +2 -2
  100. package/lib/message-list/group-styles.d.ts +1 -1
  101. package/lib/message-list/message-list.component.d.ts +2 -3
  102. package/lib/message-reactions/message-reactions.component.d.ts +2 -3
  103. package/lib/message-reactions-selector/message-reactions-selector.component.d.ts +1 -2
  104. package/lib/message-text/message-text.component.d.ts +2 -2
  105. package/lib/modal/modal.component.d.ts +1 -1
  106. package/lib/notification/notification.component.d.ts +1 -1
  107. package/lib/notification-list/notification-list.component.d.ts +0 -1
  108. package/lib/paginated-list/paginated-list.component.d.ts +5 -2
  109. package/lib/read-by.d.ts +1 -1
  110. package/lib/types.d.ts +98 -84
  111. package/lib/user-list/user-list.component.d.ts +1 -1
  112. package/lib/voice-recorder/amplitude-recorder.service.d.ts +2 -2
  113. package/lib/voice-recorder/media-recorder.d.ts +2 -2
  114. package/lib/voice-recorder/transcoder.service.d.ts +4 -4
  115. package/lib/voice-recorder/voice-recorder-wavebar/voice-recorder-wavebar.component.d.ts +0 -1
  116. package/lib/voice-recorder/voice-recorder.component.d.ts +2 -2
  117. package/lib/voice-recording/voice-recording-wavebar/voice-recording-wavebar.component.d.ts +3 -3
  118. package/lib/voice-recording/voice-recording.component.d.ts +1 -1
  119. package/package.json +15 -21
  120. package/public-api.d.ts +0 -1
  121. package/src/assets/i18n/en.ts +1 -0
  122. package/src/assets/version.ts +1 -1
  123. package/esm2020/lib/attachment-list/attachment-list.component.mjs +0 -224
  124. package/esm2020/lib/attachment-preview-list/attachment-preview-list.component.mjs +0 -55
  125. package/esm2020/lib/avatar/avatar.component.mjs +0 -160
  126. package/esm2020/lib/channel/channel.component.mjs +0 -45
  127. package/esm2020/lib/channel-header/channel-header.component.mjs +0 -72
  128. package/esm2020/lib/channel-list/channel-list.component.mjs +0 -47
  129. package/esm2020/lib/channel-preview/channel-preview.component.mjs +0 -155
  130. package/esm2020/lib/channel-query.mjs +0 -77
  131. package/esm2020/lib/channel.service.mjs +0 -1546
  132. package/esm2020/lib/chat-client.service.mjs +0 -238
  133. package/esm2020/lib/file-utils.mjs +0 -35
  134. package/esm2020/lib/message/message.component.mjs +0 -486
  135. package/esm2020/lib/message-actions-box/message-actions-box.component.mjs +0 -123
  136. package/esm2020/lib/message-bounce-prompt/message-bounce-prompt.component.mjs +0 -71
  137. package/esm2020/lib/message-input/message-input.component.mjs +0 -507
  138. package/esm2020/lib/message-list/message-list.component.mjs +0 -717
  139. package/esm2020/lib/message-reactions/message-reactions.component.mjs +0 -168
  140. package/esm2020/lib/message-reactions-selector/message-reactions-selector.component.mjs +0 -61
  141. package/esm2020/lib/message.service.mjs +0 -43
  142. package/esm2020/lib/notification-list/notification-list.component.mjs +0 -36
  143. package/esm2020/lib/paginated-list/paginated-list.component.mjs +0 -94
  144. package/esm2020/lib/stream-autocomplete-textarea.module.mjs +0 -33
  145. package/esm2020/lib/stream-textarea.module.mjs +0 -31
  146. package/esm2020/lib/types.mjs +0 -2
  147. package/esm2020/lib/virtualized-list.service.mjs +0 -271
  148. package/esm2020/lib/voice-recorder/mp3-transcoder.mjs +0 -61
  149. package/esm2020/lib/voice-recorder/transcoder.service.mjs +0 -121
  150. package/esm2020/lib/voice-recorder/voice-recorder-wavebar/voice-recorder-wavebar.component.mjs +0 -35
  151. package/esm2020/lib/voice-recorder/voice-recorder.component.mjs +0 -80
  152. package/esm2020/lib/voice-recording/voice-recording-wavebar/voice-recording-wavebar.component.mjs +0 -112
  153. package/esm2020/lib/voice-recording/voice-recording.component.mjs +0 -91
  154. package/esm2020/public-api.mjs +0 -83
  155. package/fesm2015/stream-chat-angular.mjs +0 -9152
  156. package/fesm2015/stream-chat-angular.mjs.map +0 -1
  157. package/fesm2020/stream-chat-angular.mjs.map +0 -1
  158. package/lib/channel-query.d.ts +0 -26
  159. /package/{esm2020 → esm2022}/lib/format-duration.mjs +0 -0
  160. /package/{esm2020 → esm2022}/lib/injection-tokens.mjs +0 -0
  161. /package/{esm2020 → esm2022}/lib/is-image-attachment.mjs +0 -0
  162. /package/{esm2020 → esm2022}/lib/is-on-separate-date.mjs +0 -0
  163. /package/{esm2020 → esm2022}/lib/is-safari.mjs +0 -0
  164. /package/{esm2020 → esm2022}/lib/message-input/textarea.interface.mjs +0 -0
  165. /package/{esm2020 → esm2022}/stream-chat-angular.mjs +0 -0
@@ -0,0 +1,507 @@
1
+ import { Component, ContentChild, EventEmitter, HostBinding, Inject, Input, Optional, Output, TemplateRef, ViewChild, } from '@angular/core';
2
+ import { combineLatest, Subject, timer } from 'rxjs';
3
+ import { first, map, take, tap } from 'rxjs/operators';
4
+ import { AttachmentService } from '../attachment.service';
5
+ import { textareaInjectionToken } from '../injection-tokens';
6
+ import { TextareaDirective } from './textarea.directive';
7
+ import { EmojiInputService } from './emoji-input.service';
8
+ import { v4 as uuidv4 } from 'uuid';
9
+ import { VoiceRecorderService } from './voice-recorder.service';
10
+ import * as i0 from "@angular/core";
11
+ import * as i1 from "../channel.service";
12
+ import * as i2 from "../notification.service";
13
+ import * as i3 from "../attachment.service";
14
+ import * as i4 from "./message-input-config.service";
15
+ import * as i5 from "./emoji-input.service";
16
+ import * as i6 from "../custom-templates.service";
17
+ import * as i7 from "../message-actions.service";
18
+ import * as i8 from "./voice-recorder.service";
19
+ import * as i9 from "../voice-recorder/audio-recorder.service";
20
+ import * as i10 from "@angular/common";
21
+ import * as i11 from "../avatar-placeholder/avatar-placeholder.component";
22
+ import * as i12 from "../icon/icon-placeholder/icon-placeholder.component";
23
+ import * as i13 from "../attachment-list/attachment-list.component";
24
+ import * as i14 from "../attachment-preview-list/attachment-preview-list.component";
25
+ import * as i15 from "./textarea.directive";
26
+ import * as i16 from "../message-text/message-text.component";
27
+ import * as i17 from "@ngx-translate/core";
28
+ /**
29
+ * The `MessageInput` component displays an input where users can type their messages and upload files, and sends the message to the active channel. The component can be used to compose new messages or update existing ones. To send messages, the chat user needs to have the necessary [channel capability](/chat/docs/javascript/channel_capabilities/).
30
+ */
31
+ export class MessageInputComponent {
32
+ constructor(channelService, notificationService, attachmentService, configService, textareaType, componentFactoryResolver, cdRef, emojiInputService, customTemplatesService, messageActionsService, voiceRecorderService, audioRecorder) {
33
+ this.channelService = channelService;
34
+ this.notificationService = notificationService;
35
+ this.attachmentService = attachmentService;
36
+ this.configService = configService;
37
+ this.textareaType = textareaType;
38
+ this.componentFactoryResolver = componentFactoryResolver;
39
+ this.cdRef = cdRef;
40
+ this.emojiInputService = emojiInputService;
41
+ this.customTemplatesService = customTemplatesService;
42
+ this.messageActionsService = messageActionsService;
43
+ this.voiceRecorderService = voiceRecorderService;
44
+ this.audioRecorder = audioRecorder;
45
+ /**
46
+ * Determines if the message is being dispalyed in a channel or in a [thread](/chat/docs/javascript/threads/).
47
+ */
48
+ this.mode = 'main';
49
+ /**
50
+ * Enables or disables auto focus on the textarea element
51
+ */
52
+ this.autoFocus = true;
53
+ /**
54
+ * By default the input will react to changes in `messageToEdit$` from [`MessageActionsService`](/chat/docs/sdk/angular/services/MessageActionsService/) and display the message to be edited (taking into account the current `mode`).
55
+ *
56
+ * If you don't need that behavior, you can turn this of with this flag. In that case you should create your own edit message UI.
57
+ */
58
+ this.watchForMessageToEdit = true;
59
+ /**
60
+ * Use this input to control wether a send button is rendered or not. If you don't render a send button, you can still trigger message send using the `sendMessage$` input.
61
+ */
62
+ this.displaySendButton = true;
63
+ /**
64
+ * You can enable/disable voice recordings with this input
65
+ */
66
+ this.displayVoiceRecordingButton = false;
67
+ /**
68
+ * Emits when a message was successfuly sent or updated
69
+ */
70
+ this.messageUpdate = new EventEmitter();
71
+ this.class = 'str-chat__message-input-angular-host';
72
+ this.isVoiceRecording = true;
73
+ this.textareaValue = '';
74
+ this.mentionedUsers = [];
75
+ this.typingStart$ = new Subject();
76
+ this.isCooldownInProgress = false;
77
+ this.fileInputId = uuidv4();
78
+ this.subscriptions = [];
79
+ this.isViewInited = false;
80
+ this.defaultTextareaPlaceholder = 'streamChat.Type your message';
81
+ this.slowModeTextareaPlaceholder = 'streamChat.Slow Mode ON';
82
+ this.textareaPlaceholder = this.defaultTextareaPlaceholder;
83
+ this.subscriptions.push(this.attachmentService.attachmentUploadInProgressCounter$.subscribe((counter) => {
84
+ if (counter === 0 && this.hideNotification) {
85
+ this.hideNotification();
86
+ this.hideNotification = undefined;
87
+ }
88
+ }));
89
+ this.subscriptions.push(this.channelService.activeChannel$.subscribe((channel) => {
90
+ if (channel && this.channel && channel.id !== this.channel.id) {
91
+ this.textareaValue = '';
92
+ this.attachmentService.resetAttachmentUploads();
93
+ this.voiceRecorderService.isRecorderVisible$.next(false);
94
+ }
95
+ const capabilities = channel?.data?.own_capabilities;
96
+ if (capabilities) {
97
+ this.isFileUploadAuthorized =
98
+ capabilities.indexOf('upload-file') !== -1;
99
+ this.canSendLinks = capabilities.indexOf('send-links') !== -1;
100
+ this.channel = channel;
101
+ this.setCanSendMessages();
102
+ }
103
+ }));
104
+ this.subscriptions.push(this.channelService.messageToQuote$.subscribe((m) => {
105
+ const isThreadReply = m && m.parent_id;
106
+ if ((this.mode === 'thread' && isThreadReply) ||
107
+ (this.mode === 'thread' && this.quotedMessage && !m) ||
108
+ (this.mode === 'main' && !isThreadReply)) {
109
+ this.quotedMessage = m;
110
+ }
111
+ }));
112
+ this.subscriptions.push(this.messageActionsService.messageToEdit$.subscribe((message) => {
113
+ this.messageToEdit = message;
114
+ this.checkIfInEditMode();
115
+ }));
116
+ this.attachmentUploads$ = this.attachmentService.attachmentUploads$;
117
+ this.customAttachments$ = this.attachmentService.customAttachments$;
118
+ this.attachmentUploadInProgressCounter$ =
119
+ this.attachmentService.attachmentUploadInProgressCounter$;
120
+ this.isFileUploadEnabled = this.configService.isFileUploadEnabled;
121
+ this.isMultipleFileUploadEnabled =
122
+ this.configService.isMultipleFileUploadEnabled;
123
+ this.areMentionsEnabled = this.configService.areMentionsEnabled;
124
+ this.mentionScope = this.configService.mentionScope;
125
+ this.inputMode = this.configService.inputMode;
126
+ this.subscriptions.push(this.typingStart$.subscribe(() => void this.channelService.typingStarted(this.parentMessageId)));
127
+ this.subscriptions.push(this.voiceRecorderService.isRecorderVisible$.subscribe((isVisible) => {
128
+ this.isVoiceRecording = isVisible;
129
+ }));
130
+ this.subscriptions.push(combineLatest([
131
+ this.channelService.latestMessageDateByUserByChannels$,
132
+ this.channelService.activeChannel$,
133
+ ])
134
+ .pipe(map(([latestMessages, channel]) => [latestMessages[channel?.cid || ''], channel]))
135
+ .subscribe(([latestMessageDate, channel]) => {
136
+ const cooldown = channel?.data?.cooldown &&
137
+ latestMessageDate &&
138
+ Math.round(channel?.data?.cooldown -
139
+ (new Date().getTime() - latestMessageDate.getTime()) / 1000);
140
+ if (cooldown &&
141
+ cooldown > 0 &&
142
+ (channel?.data?.own_capabilities).includes('slow-mode')) {
143
+ this.startCooldown(cooldown);
144
+ }
145
+ else if (this.isCooldownInProgress) {
146
+ this.stopCooldown();
147
+ }
148
+ }));
149
+ this.subscriptions.push(this.voiceRecorderService.recording$.subscribe((recording) => {
150
+ if (recording) {
151
+ void this.voiceRecordingReady(recording);
152
+ }
153
+ }));
154
+ }
155
+ ngOnChanges(changes) {
156
+ if (changes.message) {
157
+ this.messageToUpdateChanged();
158
+ }
159
+ if (changes.isFileUploadEnabled) {
160
+ this.configService.isFileUploadEnabled = this.isFileUploadEnabled;
161
+ }
162
+ if (changes.isMultipleFileUploadEnabled) {
163
+ this.configService.isMultipleFileUploadEnabled =
164
+ this.isMultipleFileUploadEnabled;
165
+ }
166
+ if (changes.areMentionsEnabled) {
167
+ this.configService.areMentionsEnabled = this.areMentionsEnabled;
168
+ }
169
+ if (changes.mentionScope) {
170
+ this.configService.mentionScope = this.mentionScope;
171
+ }
172
+ if (changes.mode) {
173
+ this.setCanSendMessages();
174
+ this.checkIfInEditMode();
175
+ }
176
+ if (changes.watchForMessageToEdit) {
177
+ this.checkIfInEditMode();
178
+ }
179
+ if (changes.inputMode) {
180
+ this.configService.inputMode = this.inputMode;
181
+ }
182
+ if (changes.sendMessage$) {
183
+ if (this.sendMessageSubcription) {
184
+ this.sendMessageSubcription.unsubscribe();
185
+ }
186
+ if (this.sendMessage$) {
187
+ this.sendMessageSubcription = this.sendMessage$.subscribe(() => void this.messageSent());
188
+ }
189
+ }
190
+ }
191
+ ngOnInit() {
192
+ this.subscriptions.push(this.customTemplatesService.emojiPickerTemplate$.subscribe((template) => {
193
+ this.emojiPickerTemplate = template;
194
+ this.cdRef.detectChanges();
195
+ }));
196
+ this.subscriptions.push(this.customTemplatesService.attachmentPreviewListTemplate$.subscribe((template) => {
197
+ this.attachmentPreviewListTemplate = template;
198
+ this.cdRef.detectChanges();
199
+ }));
200
+ this.subscriptions.push(this.customTemplatesService.customAttachmentUploadTemplate$.subscribe((template) => {
201
+ this.customAttachmentUploadTemplate = template;
202
+ this.cdRef.detectChanges();
203
+ }));
204
+ }
205
+ ngAfterViewInit() {
206
+ this.isViewInited = true;
207
+ this.initTextarea();
208
+ }
209
+ ngOnDestroy() {
210
+ if (this.sendMessageSubcription) {
211
+ this.sendMessageSubcription.unsubscribe();
212
+ }
213
+ this.subscriptions.forEach((s) => s.unsubscribe());
214
+ }
215
+ async messageSent() {
216
+ if (this.isCooldownInProgress) {
217
+ return;
218
+ }
219
+ let attachmentUploadInProgressCounter;
220
+ this.attachmentService.attachmentUploadInProgressCounter$
221
+ .pipe(first())
222
+ .subscribe((counter) => (attachmentUploadInProgressCounter = counter));
223
+ if (attachmentUploadInProgressCounter > 0) {
224
+ if (!this.hideNotification) {
225
+ this.hideNotification =
226
+ this.notificationService.addPermanentNotification('streamChat.Wait until all attachments have uploaded');
227
+ }
228
+ return;
229
+ }
230
+ const attachments = this.attachmentService.mapToAttachments();
231
+ let text = this.textareaValue;
232
+ text = text.replace(/^\n+/g, ''); // leading empty lines
233
+ text = text.replace(/\n+$/g, ''); // ending empty lines
234
+ const textContainsOnlySpaceChars = !text.replace(/ /g, ''); //spcae
235
+ if ((!text || textContainsOnlySpaceChars) &&
236
+ (!attachments || attachments.length === 0)) {
237
+ return;
238
+ }
239
+ if (textContainsOnlySpaceChars) {
240
+ text = '';
241
+ }
242
+ if (this.containsLinks && !this.canSendLinks) {
243
+ this.notificationService.addTemporaryNotification('streamChat.Sending links is not allowed in this conversation');
244
+ return;
245
+ }
246
+ if (!this.isUpdate) {
247
+ this.textareaValue = '';
248
+ }
249
+ try {
250
+ const message = await (this.isUpdate
251
+ ? this.channelService.updateMessage({
252
+ ...this.message,
253
+ text: text,
254
+ attachments: attachments,
255
+ })
256
+ : this.channelService.sendMessage(text, attachments, this.mentionedUsers, this.parentMessageId, this.quotedMessage?.id));
257
+ this.messageUpdate.emit({ message });
258
+ if (this.isUpdate) {
259
+ this.deselectMessageToEdit();
260
+ }
261
+ else {
262
+ this.attachmentService.resetAttachmentUploads();
263
+ }
264
+ }
265
+ catch (error) {
266
+ if (this.isUpdate) {
267
+ this.notificationService.addTemporaryNotification('streamChat.Edit message request failed');
268
+ }
269
+ }
270
+ void this.channelService.typingStopped(this.parentMessageId);
271
+ if (this.quotedMessage) {
272
+ this.deselectMessageToQuote();
273
+ }
274
+ }
275
+ get containsLinks() {
276
+ return /(?:(?:https?|ftp):\/\/)?[\w/\-?=%.]+\.[\w/\-&?=%.]+/.test(this.textareaValue);
277
+ }
278
+ get quotedMessageAttachments() {
279
+ const originalAttachments = this.quotedMessage?.attachments;
280
+ return originalAttachments && originalAttachments.length
281
+ ? [originalAttachments[0]]
282
+ : [];
283
+ }
284
+ get disabledTextareaText() {
285
+ if (!this.canSendMessages) {
286
+ return this.mode === 'thread'
287
+ ? "streamChat.You can't send thread replies in this channel"
288
+ : "streamChat.You can't send messages in this channel";
289
+ }
290
+ return '';
291
+ }
292
+ itemsPasted(event) {
293
+ if (this.configService.customPasteEventHandler) {
294
+ this.configService.customPasteEventHandler(event, this);
295
+ }
296
+ else {
297
+ if (event.clipboardData?.files && event.clipboardData?.files.length > 0) {
298
+ event.preventDefault();
299
+ void this.filesSelected(event.clipboardData?.files);
300
+ }
301
+ }
302
+ }
303
+ async filesSelected(fileList) {
304
+ await this.attachmentService.filesSelected(fileList);
305
+ this.clearFileInput();
306
+ }
307
+ deselectMessageToQuote() {
308
+ this.channelService.selectMessageToQuote(undefined);
309
+ }
310
+ deselectMessageToEdit() {
311
+ this.messageActionsService.messageToEdit$.next(undefined);
312
+ }
313
+ getEmojiPickerContext() {
314
+ return {
315
+ emojiInput$: this.emojiInputService.emojiInput$,
316
+ };
317
+ }
318
+ getAttachmentPreviewListContext() {
319
+ return {
320
+ attachmentUploads$: this.attachmentService.attachmentUploads$,
321
+ deleteUploadHandler: this.deleteUpload.bind(this),
322
+ retryUploadHandler: this.retryUpload.bind(this),
323
+ service: this.attachmentService,
324
+ };
325
+ }
326
+ getAttachmentUploadContext() {
327
+ return {
328
+ isMultipleFileUploadEnabled: this.isMultipleFileUploadEnabled,
329
+ attachmentService: this.attachmentService,
330
+ };
331
+ }
332
+ getQuotedMessageTextContext() {
333
+ return {
334
+ message: this.quotedMessage,
335
+ isQuoted: true,
336
+ shouldTranslate: true,
337
+ };
338
+ }
339
+ async startVoiceRecording() {
340
+ await this.audioRecorder?.start();
341
+ if (this.audioRecorder?.isRecording) {
342
+ this.voiceRecorderService.isRecorderVisible$.next(true);
343
+ }
344
+ }
345
+ async voiceRecordingReady(recording) {
346
+ try {
347
+ await this.attachmentService.uploadVoiceRecording(recording);
348
+ if (this.configService.sendVoiceRecordingImmediately) {
349
+ await this.messageSent();
350
+ }
351
+ }
352
+ finally {
353
+ this.voiceRecorderService.isRecorderVisible$.next(false);
354
+ }
355
+ }
356
+ get isUpdate() {
357
+ return !!this.message;
358
+ }
359
+ deleteUpload(upload) {
360
+ if (this.isUpdate) {
361
+ // Delay delete to avoid modal detecting this click as outside click
362
+ setTimeout(() => {
363
+ void this.attachmentService.deleteAttachment(upload);
364
+ });
365
+ }
366
+ else {
367
+ void this.attachmentService.deleteAttachment(upload);
368
+ }
369
+ }
370
+ retryUpload(file) {
371
+ void this.attachmentService.retryAttachmentUpload(file);
372
+ }
373
+ clearFileInput() {
374
+ this.fileInput.nativeElement.value = '';
375
+ }
376
+ initTextarea() {
377
+ // cleanup previously built textarea
378
+ if (!this.canSendMessages) {
379
+ this.textareaRef = undefined;
380
+ }
381
+ if (!this.canSendMessages || this.textareaRef || !this.textareaAnchor) {
382
+ return;
383
+ }
384
+ const componentFactory = this.componentFactoryResolver.resolveComponentFactory(this.textareaType);
385
+ this.textareaRef =
386
+ this.textareaAnchor.viewContainerRef.createComponent(componentFactory);
387
+ this.cdRef.detectChanges();
388
+ }
389
+ setCanSendMessages() {
390
+ const capabilities = this.channel?.data?.own_capabilities;
391
+ if (!capabilities) {
392
+ this.canSendMessages = false;
393
+ }
394
+ else {
395
+ this.canSendMessages =
396
+ capabilities.indexOf(this.mode === 'main' ? 'send-message' : 'send-reply') !== -1 || this.isUpdate;
397
+ }
398
+ if (this.isViewInited) {
399
+ this.cdRef.detectChanges();
400
+ this.initTextarea();
401
+ }
402
+ }
403
+ get parentMessageId() {
404
+ let parentMessageId = undefined;
405
+ if (this.mode === 'thread') {
406
+ this.channelService.activeParentMessageId$
407
+ .pipe(first())
408
+ .subscribe((id) => (parentMessageId = id));
409
+ }
410
+ return parentMessageId;
411
+ }
412
+ startCooldown(cooldown) {
413
+ this.textareaPlaceholder = this.slowModeTextareaPlaceholder;
414
+ this.isCooldownInProgress = true;
415
+ this.cooldown$ = timer(0, 1000).pipe(take(cooldown + 1), map((v) => cooldown - v), tap((v) => {
416
+ if (v === 0) {
417
+ this.stopCooldown();
418
+ }
419
+ }));
420
+ }
421
+ stopCooldown() {
422
+ this.cooldown$ = undefined;
423
+ this.isCooldownInProgress = false;
424
+ this.textareaPlaceholder = this.defaultTextareaPlaceholder;
425
+ }
426
+ checkIfInEditMode() {
427
+ if (!this.watchForMessageToEdit) {
428
+ return;
429
+ }
430
+ if (!this.messageToEdit && this.message) {
431
+ this.message = undefined;
432
+ this.messageToUpdateChanged();
433
+ if (this.isViewInited) {
434
+ this.cdRef.detectChanges();
435
+ }
436
+ }
437
+ if (this.messageToEdit &&
438
+ ((this.mode === 'main' && !this.messageToEdit.parent_id) ||
439
+ (this.mode === 'thread' && this.messageToEdit.parent_id))) {
440
+ this.message = this.messageToEdit;
441
+ this.messageToUpdateChanged();
442
+ if (this.isViewInited) {
443
+ this.cdRef.detectChanges();
444
+ }
445
+ }
446
+ }
447
+ messageToUpdateChanged() {
448
+ this.attachmentService.resetAttachmentUploads();
449
+ this.setCanSendMessages();
450
+ if (this.isUpdate) {
451
+ this.attachmentService.createFromAttachments(this.message.attachments || []);
452
+ this.textareaValue = this.message.text || '';
453
+ }
454
+ else {
455
+ this.textareaValue = '';
456
+ }
457
+ }
458
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.0", ngImport: i0, type: MessageInputComponent, deps: [{ token: i1.ChannelService }, { token: i2.NotificationService }, { token: i3.AttachmentService }, { token: i4.MessageInputConfigService }, { token: textareaInjectionToken }, { token: i0.ComponentFactoryResolver }, { token: i0.ChangeDetectorRef }, { token: i5.EmojiInputService }, { token: i6.CustomTemplatesService }, { token: i7.MessageActionsService }, { token: i8.VoiceRecorderService }, { token: i9.AudioRecorderService, optional: true }], target: i0.ɵɵFactoryTarget.Component }); }
459
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.0.0", type: MessageInputComponent, selector: "stream-message-input", inputs: { isFileUploadEnabled: "isFileUploadEnabled", areMentionsEnabled: "areMentionsEnabled", mentionScope: "mentionScope", mode: "mode", isMultipleFileUploadEnabled: "isMultipleFileUploadEnabled", message: "message", sendMessage$: "sendMessage$", inputMode: "inputMode", autoFocus: "autoFocus", watchForMessageToEdit: "watchForMessageToEdit", displaySendButton: "displaySendButton", displayVoiceRecordingButton: "displayVoiceRecordingButton" }, outputs: { messageUpdate: "messageUpdate" }, host: { properties: { "class": "this.class" } }, providers: [AttachmentService, EmojiInputService, VoiceRecorderService], queries: [{ propertyName: "voiceRecorderRef", first: true, predicate: TemplateRef, descendants: true }], viewQueries: [{ propertyName: "fileInput", first: true, predicate: ["fileInput"], descendants: true }, { propertyName: "textareaAnchor", first: true, predicate: TextareaDirective, descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div\n class=\"str-chat__message-input str-chat-angular__message-input\"\n [style.display]=\"isVoiceRecording ? 'none' : 'flex'\"\n>\n @if (quotedMessage) {\n <div class=\"str-chat__quoted-message-preview-header\">\n <div class=\"str-chat__quoted-message-reply-to-message\">\n {{ \"streamChat.Reply to Message\" | translate }}\n </div>\n <button\n class=\"str-chat__quoted-message-remove\"\n data-testid=\"remove-quote\"\n (click)=\"deselectMessageToQuote()\"\n (keyup.enter)=\"deselectMessageToQuote()\"\n >\n <stream-icon-placeholder icon=\"close\" />\n </button>\n </div>\n }\n @if (isUpdate) {\n <div class=\"str-chat__quoted-message-preview-header\">\n <div class=\"str-chat__quoted-message-reply-to-message\">\n {{ \"streamChat.Edit Message\" | translate }}\n </div>\n <button\n class=\"str-chat__quoted-message-remove\"\n data-testid=\"remove-quote\"\n (click)=\"deselectMessageToEdit()\"\n (keyup.enter)=\"deselectMessageToEdit()\"\n >\n <stream-icon-placeholder icon=\"close\" />\n </button>\n </div>\n }\n @if (canSendMessages) {\n <div\n class=\"str-chat__message-input-inner str-chat-angular__message-input-inner\"\n >\n <ng-content select=\"[message-input-start]\" />\n @if (isFileUploadEnabled && isFileUploadAuthorized && canSendMessages) {\n <ng-container\n *ngTemplateOutlet=\"\n customAttachmentUploadTemplate || defaultAttachmentUpload;\n context: getAttachmentUploadContext()\n \"\n />\n <ng-template #defaultAttachmentUpload>\n <div\n class=\"str-chat__file-input-container\"\n data-testid=\"file-upload-button\"\n >\n <input\n #fileInput\n type=\"file\"\n class=\"str-chat__file-input\"\n data-testid=\"file-input\"\n [multiple]=\"isMultipleFileUploadEnabled\"\n id=\"{{ fileInputId }}\"\n [disabled]=\"\n (attachmentService.attachmentsCounter$ | async)! >=\n attachmentService.maxNumberOfAttachments\n \"\n (change)=\"filesSelected(fileInput.files)\"\n />\n <label class=\"str-chat__file-input-label\" for=\"{{ fileInputId }}\">\n <stream-icon-placeholder icon=\"attach\" />\n </label>\n </div>\n </ng-template>\n }\n <div class=\"str-chat__message-textarea-container\">\n @if (quotedMessage) {\n <div\n data-testid=\"quoted-message-container\"\n class=\"str-chat__quoted-message-preview\"\n >\n <stream-avatar-placeholder\n data-testid=\"qouted-message-avatar\"\n class=\"str-chat-angular__avatar-host str-chat__message-sender-avatar\"\n type=\"user\"\n location=\"quoted-message-sender\"\n [imageUrl]=\"quotedMessage.user?.image\"\n [name]=\"quotedMessage.user?.name || quotedMessage.user?.id\"\n [user]=\"quotedMessage.user || undefined\"\n />\n <div\n class=\"quoted-message-preview-content-inner str-chat__quoted-message-bubble\"\n >\n @if (\n quotedMessage.attachments && quotedMessage.attachments.length\n ) {\n <stream-attachment-list\n [attachments]=\"quotedMessageAttachments\"\n [messageId]=\"quotedMessage.id\"\n />\n }\n <div class=\"str-chat__quoted-message-text\">\n <ng-container\n *ngTemplateOutlet=\"\n (customTemplatesService.messageTextTemplate$ | async) ||\n defaultText;\n context: getQuotedMessageTextContext()\n \"\n />\n <ng-template\n #defaultText\n let-message=\"message\"\n let-isQuoted=\"isQuoted\"\n let-shouldTranslate=\"shouldTranslate\"\n >\n <stream-message-text\n [message]=\"message\"\n [isQuoted]=\"isQuoted\"\n [shouldTranslate]=\"shouldTranslate\"\n data-testid=\"quoted-message-text\"\n />\n </ng-template>\n </div>\n </div>\n </div>\n }\n <ng-template\n #defaultAttachmentsPreview\n let-attachmentUploads$=\"attachmentUploads$\"\n let-retryUploadHandler=\"retryUploadHandler\"\n let-deleteUploadHandler=\"deleteUploadHandler\"\n >\n <stream-attachment-preview-list\n class=\"str-chat__attachment-preview-list-angular-host\"\n [attachmentUploads$]=\"attachmentUploads$\"\n (retryAttachmentUpload)=\"retryUploadHandler($event)\"\n (deleteAttachment)=\"deleteUploadHandler($event)\"\n />\n </ng-template>\n <ng-container\n *ngTemplateOutlet=\"\n attachmentPreviewListTemplate || defaultAttachmentsPreview;\n context: getAttachmentPreviewListContext()\n \"\n />\n <div class=\"str-chat__message-textarea-with-emoji-picker\">\n <ng-container\n streamTextarea\n [componentRef]=\"textareaRef\"\n [areMentionsEnabled]=\"areMentionsEnabled\"\n [mentionScope]=\"mentionScope\"\n [inputMode]=\"inputMode\"\n [autoFocus]=\"autoFocus\"\n [placeholder]=\"textareaPlaceholder\"\n [(value)]=\"textareaValue\"\n (valueChange)=\"typingStart$.next()\"\n (send)=\"messageSent()\"\n (userMentions)=\"mentionedUsers = $event\"\n (pasteFromClipboard)=\"itemsPasted($event)\"\n />\n @if (emojiPickerTemplate) {\n <ng-container\n *ngTemplateOutlet=\"\n emojiPickerTemplate;\n context: getEmojiPickerContext()\n \"\n />\n }\n </div>\n </div>\n @if (canSendMessages && !isCooldownInProgress && displaySendButton) {\n <button\n data-testid=\"send-button\"\n class=\"str-chat__send-button\"\n [disabled]=\"\n (attachmentUploadInProgressCounter$ | async)! > 0 ||\n (attachmentService.attachmentsCounter$ | async)! >\n attachmentService.maxNumberOfAttachments ||\n (!textareaValue &&\n (attachmentUploads$ | async)!.length === 0 &&\n (customAttachments$ | async)!.length === 0)\n \"\n (click)=\"messageSent()\"\n (keyup.enter)=\"messageSent()\"\n >\n <stream-icon-placeholder icon=\"send\" />\n </button>\n }\n @if (isCooldownInProgress) {\n <div\n class=\"str-chat__message-input-cooldown\"\n data-testid=\"cooldown-timer\"\n >\n {{ cooldown$ | async }}\n </div>\n }\n @if (displayVoiceRecordingButton) {\n <button\n class=\"str-chat__start-recording-audio-button\"\n data-testid=\"start-voice-recording\"\n [disabled]=\"\n voiceRecorderService.isRecorderVisible$.value ||\n audioRecorder?.isRecording ||\n (attachmentService.attachmentsCounter$ | async)! >=\n attachmentService.maxNumberOfAttachments\n \"\n (click)=\"startVoiceRecording()\"\n (keyup.enter)=\"startVoiceRecording()\"\n >\n <stream-icon-placeholder icon=\"mic\" />\n </button>\n }\n <ng-content select=\"[message-input-end]\" />\n </div>\n } @else {\n <div\n class=\"str-chat__message-input-not-allowed\"\n data-testid=\"disabled-textarea\"\n >\n {{ disabledTextareaText | translate }}\n </div>\n }\n</div>\n@if (voiceRecorderRef) {\n <ng-template\n [ngTemplateOutlet]=\"voiceRecorderRef\"\n [ngTemplateOutletContext]=\"{ service: voiceRecorderService }\"\n />\n}\n", dependencies: [{ kind: "directive", type: i10.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: i11.AvatarPlaceholderComponent, selector: "stream-avatar-placeholder", inputs: ["name", "imageUrl", "location", "channel", "user", "type", "initialsType", "showOnlineIndicator"] }, { kind: "component", type: i12.IconPlaceholderComponent, selector: "stream-icon-placeholder", inputs: ["icon"] }, { kind: "component", type: i13.AttachmentListComponent, selector: "stream-attachment-list", inputs: ["messageId", "parentMessageId", "attachments"], outputs: ["imageModalStateChange"] }, { kind: "component", type: i14.AttachmentPreviewListComponent, selector: "stream-attachment-preview-list", inputs: ["attachmentUploads$"], outputs: ["retryAttachmentUpload", "deleteAttachment"] }, { kind: "directive", type: i15.TextareaDirective, selector: "[streamTextarea]", inputs: ["componentRef", "areMentionsEnabled", "mentionScope", "inputMode", "value", "placeholder", "autoFocus"], outputs: ["valueChange", "send", "userMentions", "pasteFromClipboard"] }, { kind: "component", type: i16.MessageTextComponent, selector: "stream-message-text", inputs: ["message", "isQuoted", "shouldTranslate"] }, { kind: "pipe", type: i10.AsyncPipe, name: "async" }, { kind: "pipe", type: i17.TranslatePipe, name: "translate" }] }); }
460
+ }
461
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0", ngImport: i0, type: MessageInputComponent, decorators: [{
462
+ type: Component,
463
+ args: [{ selector: 'stream-message-input', providers: [AttachmentService, EmojiInputService, VoiceRecorderService], template: "<div\n class=\"str-chat__message-input str-chat-angular__message-input\"\n [style.display]=\"isVoiceRecording ? 'none' : 'flex'\"\n>\n @if (quotedMessage) {\n <div class=\"str-chat__quoted-message-preview-header\">\n <div class=\"str-chat__quoted-message-reply-to-message\">\n {{ \"streamChat.Reply to Message\" | translate }}\n </div>\n <button\n class=\"str-chat__quoted-message-remove\"\n data-testid=\"remove-quote\"\n (click)=\"deselectMessageToQuote()\"\n (keyup.enter)=\"deselectMessageToQuote()\"\n >\n <stream-icon-placeholder icon=\"close\" />\n </button>\n </div>\n }\n @if (isUpdate) {\n <div class=\"str-chat__quoted-message-preview-header\">\n <div class=\"str-chat__quoted-message-reply-to-message\">\n {{ \"streamChat.Edit Message\" | translate }}\n </div>\n <button\n class=\"str-chat__quoted-message-remove\"\n data-testid=\"remove-quote\"\n (click)=\"deselectMessageToEdit()\"\n (keyup.enter)=\"deselectMessageToEdit()\"\n >\n <stream-icon-placeholder icon=\"close\" />\n </button>\n </div>\n }\n @if (canSendMessages) {\n <div\n class=\"str-chat__message-input-inner str-chat-angular__message-input-inner\"\n >\n <ng-content select=\"[message-input-start]\" />\n @if (isFileUploadEnabled && isFileUploadAuthorized && canSendMessages) {\n <ng-container\n *ngTemplateOutlet=\"\n customAttachmentUploadTemplate || defaultAttachmentUpload;\n context: getAttachmentUploadContext()\n \"\n />\n <ng-template #defaultAttachmentUpload>\n <div\n class=\"str-chat__file-input-container\"\n data-testid=\"file-upload-button\"\n >\n <input\n #fileInput\n type=\"file\"\n class=\"str-chat__file-input\"\n data-testid=\"file-input\"\n [multiple]=\"isMultipleFileUploadEnabled\"\n id=\"{{ fileInputId }}\"\n [disabled]=\"\n (attachmentService.attachmentsCounter$ | async)! >=\n attachmentService.maxNumberOfAttachments\n \"\n (change)=\"filesSelected(fileInput.files)\"\n />\n <label class=\"str-chat__file-input-label\" for=\"{{ fileInputId }}\">\n <stream-icon-placeholder icon=\"attach\" />\n </label>\n </div>\n </ng-template>\n }\n <div class=\"str-chat__message-textarea-container\">\n @if (quotedMessage) {\n <div\n data-testid=\"quoted-message-container\"\n class=\"str-chat__quoted-message-preview\"\n >\n <stream-avatar-placeholder\n data-testid=\"qouted-message-avatar\"\n class=\"str-chat-angular__avatar-host str-chat__message-sender-avatar\"\n type=\"user\"\n location=\"quoted-message-sender\"\n [imageUrl]=\"quotedMessage.user?.image\"\n [name]=\"quotedMessage.user?.name || quotedMessage.user?.id\"\n [user]=\"quotedMessage.user || undefined\"\n />\n <div\n class=\"quoted-message-preview-content-inner str-chat__quoted-message-bubble\"\n >\n @if (\n quotedMessage.attachments && quotedMessage.attachments.length\n ) {\n <stream-attachment-list\n [attachments]=\"quotedMessageAttachments\"\n [messageId]=\"quotedMessage.id\"\n />\n }\n <div class=\"str-chat__quoted-message-text\">\n <ng-container\n *ngTemplateOutlet=\"\n (customTemplatesService.messageTextTemplate$ | async) ||\n defaultText;\n context: getQuotedMessageTextContext()\n \"\n />\n <ng-template\n #defaultText\n let-message=\"message\"\n let-isQuoted=\"isQuoted\"\n let-shouldTranslate=\"shouldTranslate\"\n >\n <stream-message-text\n [message]=\"message\"\n [isQuoted]=\"isQuoted\"\n [shouldTranslate]=\"shouldTranslate\"\n data-testid=\"quoted-message-text\"\n />\n </ng-template>\n </div>\n </div>\n </div>\n }\n <ng-template\n #defaultAttachmentsPreview\n let-attachmentUploads$=\"attachmentUploads$\"\n let-retryUploadHandler=\"retryUploadHandler\"\n let-deleteUploadHandler=\"deleteUploadHandler\"\n >\n <stream-attachment-preview-list\n class=\"str-chat__attachment-preview-list-angular-host\"\n [attachmentUploads$]=\"attachmentUploads$\"\n (retryAttachmentUpload)=\"retryUploadHandler($event)\"\n (deleteAttachment)=\"deleteUploadHandler($event)\"\n />\n </ng-template>\n <ng-container\n *ngTemplateOutlet=\"\n attachmentPreviewListTemplate || defaultAttachmentsPreview;\n context: getAttachmentPreviewListContext()\n \"\n />\n <div class=\"str-chat__message-textarea-with-emoji-picker\">\n <ng-container\n streamTextarea\n [componentRef]=\"textareaRef\"\n [areMentionsEnabled]=\"areMentionsEnabled\"\n [mentionScope]=\"mentionScope\"\n [inputMode]=\"inputMode\"\n [autoFocus]=\"autoFocus\"\n [placeholder]=\"textareaPlaceholder\"\n [(value)]=\"textareaValue\"\n (valueChange)=\"typingStart$.next()\"\n (send)=\"messageSent()\"\n (userMentions)=\"mentionedUsers = $event\"\n (pasteFromClipboard)=\"itemsPasted($event)\"\n />\n @if (emojiPickerTemplate) {\n <ng-container\n *ngTemplateOutlet=\"\n emojiPickerTemplate;\n context: getEmojiPickerContext()\n \"\n />\n }\n </div>\n </div>\n @if (canSendMessages && !isCooldownInProgress && displaySendButton) {\n <button\n data-testid=\"send-button\"\n class=\"str-chat__send-button\"\n [disabled]=\"\n (attachmentUploadInProgressCounter$ | async)! > 0 ||\n (attachmentService.attachmentsCounter$ | async)! >\n attachmentService.maxNumberOfAttachments ||\n (!textareaValue &&\n (attachmentUploads$ | async)!.length === 0 &&\n (customAttachments$ | async)!.length === 0)\n \"\n (click)=\"messageSent()\"\n (keyup.enter)=\"messageSent()\"\n >\n <stream-icon-placeholder icon=\"send\" />\n </button>\n }\n @if (isCooldownInProgress) {\n <div\n class=\"str-chat__message-input-cooldown\"\n data-testid=\"cooldown-timer\"\n >\n {{ cooldown$ | async }}\n </div>\n }\n @if (displayVoiceRecordingButton) {\n <button\n class=\"str-chat__start-recording-audio-button\"\n data-testid=\"start-voice-recording\"\n [disabled]=\"\n voiceRecorderService.isRecorderVisible$.value ||\n audioRecorder?.isRecording ||\n (attachmentService.attachmentsCounter$ | async)! >=\n attachmentService.maxNumberOfAttachments\n \"\n (click)=\"startVoiceRecording()\"\n (keyup.enter)=\"startVoiceRecording()\"\n >\n <stream-icon-placeholder icon=\"mic\" />\n </button>\n }\n <ng-content select=\"[message-input-end]\" />\n </div>\n } @else {\n <div\n class=\"str-chat__message-input-not-allowed\"\n data-testid=\"disabled-textarea\"\n >\n {{ disabledTextareaText | translate }}\n </div>\n }\n</div>\n@if (voiceRecorderRef) {\n <ng-template\n [ngTemplateOutlet]=\"voiceRecorderRef\"\n [ngTemplateOutletContext]=\"{ service: voiceRecorderService }\"\n />\n}\n" }]
464
+ }], ctorParameters: () => [{ type: i1.ChannelService }, { type: i2.NotificationService }, { type: i3.AttachmentService }, { type: i4.MessageInputConfigService }, { type: i0.Type, decorators: [{
465
+ type: Inject,
466
+ args: [textareaInjectionToken]
467
+ }] }, { type: i0.ComponentFactoryResolver }, { type: i0.ChangeDetectorRef }, { type: i5.EmojiInputService }, { type: i6.CustomTemplatesService }, { type: i7.MessageActionsService }, { type: i8.VoiceRecorderService }, { type: i9.AudioRecorderService, decorators: [{
468
+ type: Optional
469
+ }] }], propDecorators: { isFileUploadEnabled: [{
470
+ type: Input
471
+ }], areMentionsEnabled: [{
472
+ type: Input
473
+ }], mentionScope: [{
474
+ type: Input
475
+ }], mode: [{
476
+ type: Input
477
+ }], isMultipleFileUploadEnabled: [{
478
+ type: Input
479
+ }], message: [{
480
+ type: Input
481
+ }], sendMessage$: [{
482
+ type: Input
483
+ }], inputMode: [{
484
+ type: Input
485
+ }], autoFocus: [{
486
+ type: Input
487
+ }], watchForMessageToEdit: [{
488
+ type: Input
489
+ }], displaySendButton: [{
490
+ type: Input
491
+ }], displayVoiceRecordingButton: [{
492
+ type: Input
493
+ }], messageUpdate: [{
494
+ type: Output
495
+ }], voiceRecorderRef: [{
496
+ type: ContentChild,
497
+ args: [TemplateRef]
498
+ }], class: [{
499
+ type: HostBinding
500
+ }], fileInput: [{
501
+ type: ViewChild,
502
+ args: ['fileInput']
503
+ }], textareaAnchor: [{
504
+ type: ViewChild,
505
+ args: [TextareaDirective, { static: false }]
506
+ }] } });
507
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWVzc2FnZS1pbnB1dC5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9zdHJlYW0tY2hhdC1hbmd1bGFyL3NyYy9saWIvbWVzc2FnZS1pbnB1dC9tZXNzYWdlLWlucHV0LmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL3N0cmVhbS1jaGF0LWFuZ3VsYXIvc3JjL2xpYi9tZXNzYWdlLWlucHV0L21lc3NhZ2UtaW5wdXQuY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUdMLFNBQVMsRUFHVCxZQUFZLEVBRVosWUFBWSxFQUNaLFdBQVcsRUFDWCxNQUFNLEVBQ04sS0FBSyxFQUlMLFFBQVEsRUFDUixNQUFNLEVBRU4sV0FBVyxFQUVYLFNBQVMsR0FDVixNQUFNLGVBQWUsQ0FBQztBQUN2QixPQUFPLEVBQUUsYUFBYSxFQUFjLE9BQU8sRUFBZ0IsS0FBSyxFQUFFLE1BQU0sTUFBTSxDQUFDO0FBQy9FLE9BQU8sRUFBRSxLQUFLLEVBQUUsR0FBRyxFQUFFLElBQUksRUFBRSxHQUFHLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUV2RCxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSx1QkFBdUIsQ0FBQztBQUUxRCxPQUFPLEVBQUUsc0JBQXNCLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQWE3RCxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSxzQkFBc0IsQ0FBQztBQUV6RCxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSx1QkFBdUIsQ0FBQztBQUUxRCxPQUFPLEVBQUUsRUFBRSxJQUFJLE1BQU0sRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUVwQyxPQUFPLEVBQUUsb0JBQW9CLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQzs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUdoRTs7R0FFRztBQU9ILE1BQU0sT0FBTyxxQkFBcUI7SUFrR2hDLFlBQ1UsY0FB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QWEsR0FBRyxFQUFFLENBQUM7U0FDekI7SUFDSCxDQUFDOzhHQTdrQlUscUJBQXFCLDZKQXVHdEIsc0JBQXNCO2tHQXZHckIscUJBQXFCLDZrQkFGckIsQ0FBQyxpQkFBaUIsRUFBRSxpQkFBaUIsRUFBRSxvQkFBb0IsQ0FBQyx3RUE2RHpELFdBQVcseUxBNEJkLGlCQUFpQixxRUNqSjlCLHlvUUFnT0E7OzJGRHRLYSxxQkFBcUI7a0JBTmpDLFNBQVM7K0JBQ0Usc0JBQXNCLGFBR3JCLENBQUMsaUJBQWlCLEVBQUUsaUJBQWlCLEVBQUUsb0JBQW9CLENBQUM7OzBCQXlHcEUsTUFBTTsyQkFBQyxzQkFBc0I7OzBCQVE3QixRQUFRO3lDQXpHRixtQkFBbUI7c0JBQTNCLEtBQUs7Z0JBSUcsa0JBQWtCO3NCQUExQixLQUFLO2dCQUlHLFlBQVk7c0JBQXBCLEtBQUs7Z0JBSUcsSUFBSTtzQkFBWixLQUFLO2dCQUlHLDJCQUEyQjtzQkFBbkMsS0FBSztnQkFJRyxPQUFPO3NCQUFmLEtBQUs7Z0JBSUcsWUFBWTtzQkFBcEIsS0FBSztnQkFJRyxTQUFTO3NCQUFqQixLQUFLO2dCQUlHLFNBQVM7c0JBQWpCLEtBQUs7Z0JBTUcscUJBQXFCO3NCQUE3QixLQUFLO2dCQUlHLGlCQUFpQjtzQkFBekIsS0FBSztnQkFJRywyQkFBMkI7c0JBQW5DLEtBQUs7Z0JBSWEsYUFBYTtzQkFBL0IsTUFBTTtnQkFHb0IsZ0JBQWdCO3NCQUExQyxZQUFZO3VCQUFDLFdBQVc7Z0JBR1YsS0FBSztzQkFBbkIsV0FBVztnQkF3Qm9CLFNBQVM7c0JBQXhDLFNBQVM7dUJBQUMsV0FBVztnQkFFZCxjQUFjO3NCQURyQixTQUFTO3VCQUFDLGlCQUFpQixFQUFFLEVBQUUsTUFBTSxFQUFFLEtBQUssRUFBRSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XG4gIEFmdGVyVmlld0luaXQsXG4gIENoYW5nZURldGVjdG9yUmVmLFxuICBDb21wb25lbnQsXG4gIENvbXBvbmVudEZhY3RvcnlSZXNvbHZlcixcbiAgQ29tcG9uZW50UmVmLFxuICBDb250ZW50Q2hpbGQsXG4gIEVsZW1lbnRSZWYsXG4gIEV2ZW50RW1pdHRlcixcbiAgSG9zdEJpbmRpbmcsXG4gIEluamVjdCxcbiAgSW5wdXQsXG4gIE9uQ2hhbmdlcyxcbiAgT25EZXN0cm95LFxuICBPbkluaXQsXG4gIE9wdGlvbmFsLFxuICBPdXRwdXQsXG4gIFNpbXBsZUNoYW5nZXMsXG4gIFRlbXBsYXRlUmVmLFxuICBUeXBlLFxuICBWaWV3Q2hpbGQsXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgY29tYmluZUxhdGVzdCwgT2JzZXJ2YWJsZSwgU3ViamVjdCwgU3Vic2NyaXB0aW9uLCB0aW1lciB9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHsgZmlyc3QsIG1hcCwgdGFrZSwgdGFwIH0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xuaW1wb3J0IHsgQXR0YWNobWVudCwgQ2hhbm5lbCwgVXNlclJlc3BvbnNlIH0gZnJvbSAnc3RyZWFtLWNoYXQnO1xuaW1wb3J0IHsgQXR0YWNobWVudFNlcnZpY2UgfSBmcm9tICcuLi9hdHRhY2htZW50LnNlcnZpY2UnO1xuaW1wb3J0IHsgQ2hhbm5lbFNlcnZpY2UgfSBmcm9tICcuLi9jaGFubmVsLnNlcnZpY2UnO1xuaW1wb3J0IHsgdGV4dGFyZWFJbmplY3Rpb25Ub2tlbiB9IGZyb20gJy4uL2luamVjdGlvbi10b2tlbnMnO1xuaW1wb3J0IHsgTm90aWZpY2F0aW9uU2VydmljZSB9IGZyb20gJy4uL25vdGlmaWNhdGlvbi5zZXJ2aWNlJztcbmltcG9ydCB7XG4gIEF0dGFjaG1lbnRQcmV2aWV3TGlzdENvbnRleHQsXG4gIEF0dGFjaG1lbnRVcGxvYWQsXG4gIEF1ZGlvUmVjb3JkaW5nLFxuICBDdXN0b21BdHRhY2htZW50VXBsb2FkQ29udGV4dCxcbiAgRGVmYXVsdFN0cmVhbUNoYXRHZW5lcmljcyxcbiAgRW1vamlQaWNrZXJDb250ZXh0LFxuICBNZXNzYWdlVGV4dENvbnRleHQsXG4gIFN0cmVhbU1lc3NhZ2UsXG59IGZyb20gJy4uL3R5cGVzJztcbmltcG9ydCB7IE1lc3NhZ2VJbnB1dENvbmZpZ1NlcnZpY2UgfSBmcm9tICcuL21lc3NhZ2UtaW5wdXQtY29uZmlnLnNlcnZpY2UnO1xuaW1wb3J0IHsgVGV4dGFyZWFEaXJlY3RpdmUgfSBmcm9tICcuL3RleHRhcmVhLmRpcmVjdGl2ZSc7XG5pbXBvcnQgeyBUZXh0YXJlYUludGVyZmFjZSB9IGZyb20gJy4vdGV4dGFyZWEuaW50ZXJmYWNlJztcbmltcG9ydCB7IEVtb2ppSW5wdXRTZXJ2aWNlIH0gZnJvbSAnLi9lbW9qaS1pbnB1dC5zZXJ2aWNlJztcbmltcG9ydCB7IEN1c3RvbVRlbXBsYXRlc1NlcnZpY2UgfSBmcm9tICcuLi9jdXN0b20tdGVtcGxhdGVzLnNlcnZpY2UnO1xuaW1wb3J0IHsgdjQgYXMgdXVpZHY0IH0gZnJvbSAndXVpZCc7XG5pbXBvcnQgeyBNZXNzYWdlQWN0aW9uc1NlcnZpY2UgfSBmcm9tICcuLi9tZXNzYWdlLWFjdGlvbnMuc2VydmljZSc7XG5pbXBvcnQgeyBWb2ljZVJlY29yZGVyU2VydmljZSB9IGZyb20gJy4vdm9pY2UtcmVjb3JkZXIuc2VydmljZSc7XG5pbXBvcnQgeyBBdWRpb1JlY29yZGVyU2VydmljZSB9IGZyb20gJy4uL3ZvaWNlLXJlY29yZGVyL2F1ZGlvLXJlY29yZGVyLnNlcnZpY2UnO1xuXG4vKipcbiAqIFRoZSBgTWVzc2FnZUlucHV0YCBjb21wb25lbnQgZGlzcGxheXMgYW4gaW5wdXQgd2hlcmUgdXNlcnMgY2FuIHR5cGUgdGhlaXIgbWVzc2FnZXMgYW5kIHVwbG9hZCBmaWxlcywgYW5kIHNlbmRzIHRoZSBtZXNzYWdlIHRvIHRoZSBhY3RpdmUgY2hhbm5lbC4gVGhlIGNvbXBvbmVudCBjYW4gYmUgdXNlZCB0byBjb21wb3NlIG5ldyBtZXNzYWdlcyBvciB1cGRhdGUgZXhpc3Rpbmcgb25lcy4gVG8gc2VuZCBtZXNzYWdlcywgdGhlIGNoYXQgdXNlciBuZWVkcyB0byBoYXZlIHRoZSBuZWNlc3NhcnkgW2NoYW5uZWwgY2FwYWJpbGl0eV0oL2NoYXQvZG9jcy9qYXZhc2NyaXB0L2NoYW5uZWxfY2FwYWJpbGl0aWVzLykuXG4gKi9cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ3N0cmVhbS1tZXNzYWdlLWlucHV0JyxcbiAgdGVtcGxhdGVVcmw6ICcuL21lc3NhZ2UtaW5wdXQuY29tcG9uZW50Lmh0bWwnLFxuICBzdHlsZXM6IFtdLFxuICBwcm92aWRlcnM6IFtBdHRhY2htZW50U2VydmljZSwgRW1vamlJbnB1dFNlcnZpY2UsIFZvaWNlUmVjb3JkZXJTZXJ2aWNlXSxcbn0pXG5leHBvcnQgY2xhc3MgTWVzc2FnZUlucHV0Q29tcG9uZW50XG4gIGltcGxlbWVudHMgT25Jbml0LCBPbkNoYW5nZXMsIE9uRGVzdHJveSwgQWZ0ZXJWaWV3SW5pdFxue1xuICAvKipcbiAgICogSWYgZmlsZSB1cGxvYWQgaXMgZW5hYmxlZCwgdGhlIHVzZXIgY2FuIG9wZW4gYSBmaWxlIHNlbGVjdG9yIGZyb20gdGhlIGlucHV0LiBQbGVhc2Ugbm90ZSB0aGF0IHRoZSB1c2VyIGFsc28gbmVlZHMgdG8gaGF2ZSB0aGUgbmVjZXNzYXJ5IFtjaGFubmVsIGNhcGFiaWxpdHldKC9jaGF0L2RvY3MvamF2YXNjcmlwdC9jaGFubmVsX2NhcGFiaWxpdGllcy8pLiBJZiBubyB2YWx1ZSBpcyBwcm92aWRlZCwgaXQgaXMgc2V0IGZyb20gdGhlIFtgTWVzc2FnZUlucHV0Q29uZmlnU2VydmljZWBdKC9jaGF0L2RvY3Mvc2RrL2FuZ3VsYXIvc2VydmljZXMvTWVzc2FnZUlucHV0Q29uZmlnU2VydmljZS8pLlxuICAgKi9cbiAgQElucHV0KCkgaXNGaWxlVXBsb2FkRW5hYmxlZDogYm9vbGVhbiB8IHVuZGVmaW5lZDtcbiAgLyoqXG4gICAqIElmIHRydWUsIHVzZXJzIGNhbiBtZW50aW9uIG90aGVyIHVzZXJzIGluIG1lc3NhZ2VzLiBZb3UgYWxzbyBbbmVlZCB0byB1c2UgdGhlIGBBdXRvY29tcGxldGVUZXh0YXJlYWBdKC9jaGF0L2RvY3Mvc2RrL2FuZ3VsYXIvY29uY2VwdHMvb3B0LWluLWFyY2hpdGVjdHVyZS8pIGZvciB0aGlzIGZlYXR1cmUgdG8gd29yay4gSWYgbm8gdmFsdWUgaXMgcHJvdmlkZWQsIGl0IGlzIHNldCBmcm9tIHRoZSBbYE1lc3NhZ2VJbnB1dENvbmZpZ1NlcnZpY2VgXSgvY2hhdC9kb2NzL3Nkay9hbmd1bGFyL3NlcnZpY2VzL01lc3NhZ2VJbnB1dENvbmZpZ1NlcnZpY2UvKS5cbiAgICovXG4gIEBJbnB1dCgpIGFyZU1lbnRpb25zRW5hYmxlZDogYm9vbGVhbiB8IHVuZGVmaW5lZDtcbiAgLyoqXG4gICAqIFRoZSBzY29wZSBmb3IgdXNlciBtZW50aW9ucywgZWl0aGVyIG1lbWJlcnMgb2YgdGhlIGN1cnJlbnQgY2hhbm5lbCBvZiBtZW1iZXJzIG9mIHRoZSBhcHBsaWNhdGlvbi4gSWYgbm8gdmFsdWUgaXMgcHJvdmlkZWQsIGl0IGlzIHNldCBmcm9tIHRoZSBbYE1lc3NhZ2VJbnB1dENvbmZpZ1NlcnZpY2VgXSgvY2hhdC9kb2NzL3Nkay9hbmd1bGFyL3NlcnZpY2VzL01lc3NhZ2VJbnB1dENvbmZpZ1NlcnZpY2UvKS5cbiAgICovXG4gIEBJbnB1dCgpIG1lbnRpb25TY29wZTogJ2NoYW5uZWwnIHwgJ2FwcGxpY2F0aW9uJyB8IHVuZGVmaW5lZDtcbiAgLyoqXG4gICAqIERldGVybWluZXMgaWYgdGhlIG1lc3NhZ2UgaXMgYmVpbmcgZGlzcGFseWVkIGluIGEgY2hhbm5lbCBvciBpbiBhIFt0aHJlYWRdKC9jaGF0L2RvY3MvamF2YXNjcmlwdC90aHJlYWRzLykuXG4gICAqL1xuICBASW5wdXQoKSBtb2RlOiAndGhyZWFkJyB8ICdtYWluJyA9ICdtYWluJztcbiAgLyoqXG4gICAqIElmIHRydWUsIHVzZXJzIGNhbiBzZWxlY3QgbXVsdGlwbGUgZmlsZXMgdG8gdXBsb2FkLiBJZiBubyB2YWx1ZSBpcyBwcm92aWRlZCwgaXQgaXMgc2V0IGZyb20gdGhlIFtgTWVzc2FnZUlucHV0Q29uZmlnU2VydmljZWBdKC9jaGF0L2RvY3Mvc2RrL2FuZ3VsYXIvc2VydmljZXMvTWVzc2FnZUlucHV0Q29uZmlnU2VydmljZS8pLlxuICAgKi9cbiAgQElucHV0KCkgaXNNdWx0aXBsZUZpbGVVcGxvYWRFbmFibGVkOiBib29sZWFuIHwgdW5kZWZpbmVkO1xuICAvKipcbiAgICogVGhlIG1lc3NhZ2UgdG8gZWRpdFxuICAgKi9cbiAgQElucHV0KCkgbWVzc2FnZTogU3RyZWFtTWVzc2FnZSB8IHVuZGVmaW5lZDtcbiAgLyoqXG4gICAqIEFuIG9ic2VydmFibGUgdGhhdCBjYW4gYmUgdXNlZCB0byB0cmlnZ2VyIG1lc3NhZ2Ugc2VuZGluZyBmcm9tIHRoZSBvdXRzaWRlXG4gICAqL1xuICBASW5wdXQoKSBzZW5kTWVzc2FnZSQ6IE9ic2VydmFibGU8dm9pZD4gfCB1bmRlZmluZWQ7XG4gIC8qKlxuICAgKiBJbiBgZGVza3RvcGAgbW9kZSB0aGUgYEVudGVyYCBrZXkgd2lsbCB0cmlnZ2VyIG1lc3NhZ2Ugc2VuZGluZywgaW4gYG1vYmlsZWAgbW9kZSB0aGUgYEVudGVyYCBrZXkgd2lsbCBpbnNlcnQgYSBuZXcgbGluZSB0byB0aGUgbWVzc2FnZSBpbnB1dC4gSWYgbm8gdmFsdWUgaXMgcHJvdmlkZWQsIGl0IGlzIHNldCBmcm9tIHRoZSBbYE1lc3NhZ2VJbnB1dENvbmZpZ1NlcnZpY2VgXSgvY2hhdC9kb2NzL3Nkay9hbmd1bGFyL3NlcnZpY2VzL01lc3NhZ2VJbnB1dENvbmZpZ1NlcnZpY2UvKS5cbiAgICovXG4gIEBJbnB1dCgpIGlucHV0TW9kZTogJ2Rlc2t0b3AnIHwgJ21vYmlsZSc7XG4gIC8qKlxuICAgKiBFbmFibGVzIG9yIGRpc2FibGVzIGF1dG8gZm9jdXMgb24gdGhlIHRleHRhcmVhIGVsZW1lbnRcbiAgICovXG4gIEBJbnB1dCgpIGF1dG9Gb2N1cyA9IHRydWU7XG4gIC8qKlxuICAgKiBCeSBkZWZhdWx0IHRoZSBpbnB1dCB3aWxsIHJlYWN0IHRvIGNoYW5nZXMgaW4gYG1lc3NhZ2VUb0VkaXQkYCBmcm9tIFtgTWVzc2FnZUFjdGlvbnNTZXJ2aWNlYF0oL2NoYXQvZG9jcy9zZGsvYW5ndWxhci9zZXJ2aWNlcy9NZXNzYWdlQWN0aW9uc1NlcnZpY2UvKSBhbmQgZGlzcGxheSB0aGUgbWVzc2FnZSB0byBiZSBlZGl0ZWQgKHRha2luZyBpbnRvIGFjY291bnQgdGhlIGN1cnJlbnQgYG1vZGVgKS5cbiAgICpcbiAgICogSWYgeW91IGRvbid0IG5lZWQgdGhhdCBiZWhhdmlvciwgeW91IGNhbiB0dXJuIHRoaXMgb2Ygd2l0aCB0aGlzIGZsYWcuIEluIHRoYXQgY2FzZSB5b3Ugc2hvdWxkIGNyZWF0ZSB5b3VyIG93biBlZGl0IG1lc3NhZ2UgVUkuXG4gICAqL1xuICBASW5wdXQoKSB3YXRjaEZvck1lc3NhZ2VUb0VkaXQgPSB0cnVlO1xuICAvKipcbiAgICogVXNlIHRoaXMgaW5wdXQgdG8gY29udHJvbCB3ZXRoZXIgYSBzZW5kIGJ1dHRvbiBpcyByZW5kZXJlZCBvciBub3QuIElmIHlvdSBkb24ndCByZW5kZXIgYSBzZW5kIGJ1dHRvbiwgeW91IGNhbiBzdGlsbCB0cmlnZ2VyIG1lc3NhZ2Ugc2VuZCB1c2luZyB0aGUgYHNlbmRNZXNzYWdlJGAgaW5wdXQuXG4gICAqL1xuICBASW5wdXQoKSBkaXNwbGF5U2VuZEJ1dHRvbiA9IHRydWU7XG4gIC8qKlxuICAgKiBZb3UgY2FuIGVuYWJsZS9kaXNhYmxlIHZvaWNlIHJlY29yZGluZ3Mgd2l0aCB0aGlzIGlucHV0XG4gICAqL1xuICBASW5wdXQoKSBkaXNwbGF5Vm9pY2VSZWNvcmRpbmdCdXR0b24gPSBmYWxzZTtcbiAgLyoqXG4gICAqIEVtaXRzIHdoZW4gYSBtZXNzYWdlIHdhcyBzdWNjZXNzZnVseSBzZW50IG9yIHVwZGF0ZWRcbiAgICovXG4gIEBPdXRwdXQoKSByZWFkb25seSBtZXNzYWdlVXBkYXRlID0gbmV3IEV2ZW50RW1pdHRlcjx7XG4gICAgbWVzc2FnZTogU3RyZWFtTWVzc2FnZTtcbiAgfT4oKTtcbiAgQENvbnRlbnRDaGlsZChUZW1wbGF0ZVJlZikgdm9pY2VSZWNvcmRlclJlZjpcbiAgICB8IFRlbXBsYXRlUmVmPHsgc2VydmljZTogVm9pY2VSZWNvcmRlclNlcnZpY2UgfT5cbiAgICB8IHVuZGVmaW5lZDtcbiAgQEhvc3RCaW5kaW5nKCkgY2xhc3MgPSAnc3RyLWNoYXRfX21lc3NhZ2UtaW5wdXQtYW5ndWxhci1ob3N0JztcbiAgaXNWb2ljZVJlY29yZGluZyA9IHRydWU7XG4gIGlzRmlsZVVwbG9hZEF1dGhvcml6ZWQ6IGJvb2xlYW4gfCB1bmRlZmluZWQ7XG4gIGNhblNlbmRMaW5rczogYm9vbGVhbiB8IHVuZGVmaW5lZDtcbiAgY2FuU2VuZE1lc3NhZ2VzOiBib29sZWFuIHwgdW5kZWZpbmVkO1xuICBhdHRhY2htZW50VXBsb2FkcyQ6IE9ic2VydmFibGU8QXR0YWNobWVudFVwbG9hZFtdPjtcbiAgY3VzdG9tQXR0YWNobWVudHMkOiBPYnNlcnZhYmxlPEF0dGFjaG1lbnRbXT47XG4gIGF0dGFjaG1lbnRVcGxvYWRJblByb2dyZXNzQ291bnRlciQ6IE9ic2VydmFibGU8bnVtYmVyPjtcbiAgdGV4dGFyZWFWYWx1ZSA9ICcnO1xuICB0ZXh0YXJlYVJlZjogQ29tcG9uZW50UmVmPFRleHRhcmVhSW50ZXJmYWNlICYgUGFydGlhbDxPbkNoYW5nZXM+PiB8IHVuZGVmaW5lZDtcbiAgbWVudGlvbmVkVXNlcnM6IFVzZXJSZXNwb25zZVtdID0gW107XG4gIHF1b3RlZE1lc3NhZ2U6IHVuZGVmaW5lZCB8IFN0cmVhbU1lc3NhZ2U7XG4gIHR5cGluZ1N0YXJ0JCA9IG5ldyBTdWJqZWN0PHZvaWQ+KCk7XG4gIGNvb2xkb3duJDogT2JzZXJ2YWJsZTxudW1iZXI+IHwgdW5kZWZpbmVkO1xuICBpc0Nvb2xkb3duSW5Qcm9ncmVzcyA9IGZhbHNlO1xuICBlbW9qaVBpY2tlclRlbXBsYXRlOiBUZW1wbGF0ZVJlZjxFbW9qaVBpY2tlckNvbnRleHQ+IHwgdW5kZWZpbmVkO1xuICBjdXN0b21BdHRhY2htZW50VXBsb2FkVGVtcGxhdGU6XG4gICAgfCBUZW1wbGF0ZVJlZjxDdXN0b21BdHRhY2htZW50VXBsb2FkQ29udGV4dD5cbiAgICB8IHVuZGVmaW5lZDtcbiAgYXR0YWNobWVudFByZXZpZXdMaXN0VGVtcGxhdGU6XG4gICAgfCBUZW1wbGF0ZVJlZjxBdHRhY2htZW50UHJldmlld0xpc3RDb250ZXh0PlxuICAgIHwgdW5kZWZpbmVkO1xuICB0ZXh0YXJlYVBsYWNlaG9sZGVyOiBzdHJpbmc7XG4gIGZpbGVJbnB1dElkID0gdXVpZHY0KCk7XG4gIEBWaWV3Q2hpbGQoJ2ZpbGVJbnB1dCcpIHByaXZhdGUgZmlsZUlucHV0ITogRWxlbWVudFJlZjxIVE1MSW5wdXRFbGVtZW50PjtcbiAgQFZpZXdDaGlsZChUZXh0YXJlYURpcmVjdGl2ZSwgeyBzdGF0aWM6IGZhbHNlIH0pXG4gIHByaXZhdGUgdGV4dGFyZWFBbmNob3IhOiBUZXh0YXJlYURpcmVjdGl2ZTtcbiAgcHJpdmF0ZSBzdWJzY3JpcHRpb25zOiBTdWJzY3JpcHRpb25bXSA9IFtdO1xuICBwcml2YXRlIGhpZGVOb3RpZmljYXRpb246ICgoKSA9PiB2b2lkKSB8IHVuZGVmaW5lZDtcbiAgcHJpdmF0ZSBpc1ZpZXdJbml0ZWQgPSBmYWxzZTtcbiAgcHJpdmF0ZSBjaGFubmVsOiBDaGFubmVsPERlZmF1bHRTdHJlYW1DaGF0R2VuZXJpY3M+IHwgdW5kZWZpbmVkO1xuICBwcml2YXRlIHNlbmRNZXNzYWdlU3ViY3JpcHRpb246IFN1YnNjcmlwdGlvbiB8IHVuZGVmaW5lZDtcbiAgcHJpdmF0ZSByZWFkb25seSBkZWZhdWx0VGV4dGFyZWFQbGFjZWhvbGRlciA9ICdzdHJlYW1DaGF0LlR5cGUgeW91ciBtZXNzYWdlJztcbiAgcHJpdmF0ZSByZWFkb25seSBzbG93TW9kZVRleHRhcmVhUGxhY2Vob2xkZXIgPSAnc3RyZWFtQ2hhdC5TbG93IE1vZGUgT04nO1xuICBwcml2YXRlIG1lc3NhZ2VUb0VkaXQ/OiBTdHJlYW1NZXNzYWdlO1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHByaXZhdGUgY2hhbm5lbFNlcnZpY2U6IENoYW5uZWxTZXJ2aWNlLFxuICAgIHByaXZhdGUgbm90aWZpY2F0aW9uU2VydmljZTogTm90aWZpY2F0aW9uU2VydmljZSxcbiAgICBwdWJsaWMgcmVhZG9ubHkgYXR0YWNobWVudFNlcnZpY2U6IEF0dGFjaG1lbnRTZXJ2aWNlLFxuICAgIHByaXZhdGUgY29uZmlnU2VydmljZTogTWVzc2FnZUlucHV0Q29uZmlnU2VydmljZSxcbiAgICBASW5qZWN0KHRleHRhcmVhSW5qZWN0aW9uVG9rZW4pXG4gICAgcHJpdmF0ZSB0ZXh0YXJlYVR5cGU6IFR5cGU8VGV4dGFyZWFJbnRlcmZhY2U+LFxuICAgIHByaXZhdGUgY29tcG9uZW50RmFjdG9yeVJlc29sdmVyOiBDb21wb25lbnRGYWN0b3J5UmVzb2x2ZXIsXG4gICAgcHJpdmF0ZSBjZFJlZjogQ2hhbmdlRGV0ZWN0b3JSZWYsXG4gICAgcHJpdmF0ZSBlbW9qaUlucHV0U2VydmljZTogRW1vamlJbnB1dFNlcnZpY2UsXG4gICAgcmVhZG9ubHkgY3VzdG9tVGVtcGxhdGVzU2VydmljZTogQ3VzdG9tVGVtcGxhdGVzU2VydmljZSxcbiAgICBwcml2YXRlIG1lc3NhZ2VBY3Rpb25zU2VydmljZTogTWVzc2FnZUFjdGlvbnNTZXJ2aWNlLFxuICAgIHB1YmxpYyByZWFkb25seSB2b2ljZVJlY29yZGVyU2VydmljZTogVm9pY2VSZWNvcmRlclNlcnZpY2UsXG4gICAgQE9wdGlvbmFsKCkgcHVibGljIGF1ZGlvUmVjb3JkZXI/OiBBdWRpb1JlY29yZGVyU2VydmljZSxcbiAgKSB7XG4gICAgdGhpcy50ZXh0YXJlYVBsYWNlaG9sZGVyID0gdGhpcy5kZWZhdWx0VGV4dGFyZWFQbGFjZWhvbGRlcjtcbiAgICB0aGlzLnN1YnNjcmlwdGlvbnMucHVzaChcbiAgICAgIHRoaXMuYXR0YWNobWVudFNlcnZpY2UuYXR0YWNobWVudFVwbG9hZEluUHJvZ3Jlc3NDb3VudGVyJC5zdWJzY3JpYmUoXG4gICAgICAgIChjb3VudGVyKSA9PiB7XG4gICAgICAgICAgaWYgKGNvdW50ZXIgPT09IDAgJiYgdGhpcy5oaWRlTm90aWZpY2F0aW9uKSB7XG4gICAgICAgICAgICB0aGlzLmhpZGVOb3RpZmljYXRpb24oKTtcbiAgICAgICAgICAgIHRoaXMuaGlkZU5vdGlmaWNhdGlvbiA9IHVuZGVmaW5lZDtcbiAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICApLFxuICAgICk7XG4gICAgdGhpcy5zdWJzY3JpcHRpb25zLnB1c2goXG4gICAgICB0aGlzLmNoYW5uZWxTZXJ2aWNlLmFjdGl2ZUNoYW5uZWwkLnN1YnNjcmliZSgoY2hhbm5lbCkgPT4ge1xuICAgICAgICBpZiAoY2hhbm5lbCAmJiB0aGlzLmNoYW5uZWwgJiYgY2hhbm5lbC5pZCAhPT0gdGhpcy5jaGFubmVsLmlkKSB7XG4gICAgICAgICAgdGhpcy50ZXh0YXJlYVZhbHVlID0gJyc7XG4gICAgICAgICAgdGhpcy5hdHRhY2htZW50U2VydmljZS5yZXNldEF0dGFjaG1lbnRVcGxvYWRzKCk7XG4gICAgICAgICAgdGhpcy52b2ljZVJlY29yZGVyU2VydmljZS5pc1JlY29yZGVyVmlzaWJsZSQubmV4dChmYWxzZSk7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgY2FwYWJpbGl0aWVzID0gY2hhbm5lbD8uZGF0YT8ub3duX2NhcGFiaWxpdGllcyBhcyBzdHJpbmdbXTtcbiAgICAgICAgaWYgKGNhcGFiaWxpdGllcykge1xuICAgICAgICAgIHRoaXMuaXNGaWxlVXBsb2FkQXV0aG9yaXplZCA9XG4gICAgICAgICAgICBjYXBhYmlsaXRpZXMuaW5kZXhPZigndXBsb2FkLWZpbGUnKSAhPT0gLTE7XG4gICAgICAgICAgdGhpcy5jYW5TZW5kTGlua3MgPSBjYXBhYmlsaXRpZXMuaW5kZXhPZignc2VuZC1saW5rcycpICE9PSAtMTtcbiAgICAgICAgICB0aGlzLmNoYW5uZWwgPSBjaGFubmVsO1xuICAgICAgICAgIHRoaXMuc2V0Q2FuU2VuZE1lc3NhZ2VzKCk7XG4gICAgICAgIH1cbiAgICAgIH0pLFxuICAgICk7XG4gICAgdGhpcy5zdWJzY3JpcHRpb25zLnB1c2goXG4gICAgICB0aGlzLmNoYW5uZWxTZXJ2aWNlLm1lc3NhZ2VUb1F1b3RlJC5zdWJzY3JpYmUoKG0pID0+IHtcbiAgICAgICAgY29uc3QgaXNUaHJlYWRSZXBseSA9IG0gJiYgbS5wYXJlbnRfaWQ7XG4gICAgICAgIGlmIChcbiAgICAgICAgICAodGhpcy5tb2RlID09PSAndGhyZWFkJyAmJiBpc1RocmVhZFJlcGx5KSB8fFxuICAgICAgICAgICh0aGlzLm1vZGUgPT09ICd0aHJlYWQnICYmIHRoaXMucXVvdGVkTWVzc2FnZSAmJiAhbSkgfHxcbiAgICAgICAgICAodGhpcy5tb2RlID09PSAnbWFpbicgJiYgIWlzVGhyZWFkUmVwbHkpXG4gICAgICAgICkge1xuICAgICAgICAgIHRoaXMucXVvdGVkTWVzc2FnZSA9IG07XG4gICAgICAgIH1cbiAgICAgIH0pLFxuICAgICk7XG4gICAgdGhpcy5zdWJzY3JpcHRpb25zLnB1c2goXG4gICAgICB0aGlzLm1lc3NhZ2VBY3Rpb25zU2VydmljZS5tZXNzYWdlVG9FZGl0JC5zdWJzY3JpYmUoKG1lc3NhZ2UpID0+IHtcbiAgICAgICAgdGhpcy5tZXNzYWdlVG9FZGl0ID0gbWVzc2FnZTtcbiAgICAgICAgdGhpcy5jaGVja0lmSW5FZGl0TW9kZSgpO1xuICAgICAgfSksXG4gICAgKTtcbiAgICB0aGlzLmF0dGFjaG1lbnRVcGxvYWRzJCA9IHRoaXMuYXR0YWNobWVudFNlcnZpY2UuYXR0YWNobWVudFVwbG9hZHMkO1xuICAgIHRoaXMuY3VzdG9tQXR0YWNobWVudHMkID0gdGhpcy5hdHRhY2htZW50U2VydmljZS5jdXN0b21BdHRhY2htZW50cyQ7XG4gICAgdGhpcy5hdHRhY2htZW50VXBsb2FkSW5Qcm9ncmVzc0NvdW50ZXIkID1cbiAgICAgIHRoaXMuYXR0YWNobWVudFNlcnZpY2UuYXR0YWNobWVudFVwbG9hZEluUHJvZ3Jlc3NDb3VudGVyJDtcbiAgICB0aGlzLmlzRmlsZVVwbG9hZEVuYWJsZWQgPSB0aGlzLmNvbmZpZ1NlcnZpY2UuaXNGaWxlVXBsb2FkRW5hYmxlZDtcbiAgICB0aGlzLmlzTXVsdGlwbGVGaWxlVXBsb2FkRW5hYmxlZCA9XG4gICAgICB0aGlzLmNvbmZpZ1NlcnZpY2UuaXNNdWx0aXBsZUZpbGVVcGxvYWRFbmFibGVkO1xuICAgIHRoaXMuYXJlTWVudGlvbnNFbmFibGVkID0gdGhpcy5jb25maWdTZXJ2aWNlLmFyZU1lbnRpb25zRW5hYmxlZDtcbiAgICB0aGlzLm1lbnRpb25TY29wZSA9IHRoaXMuY29uZmlnU2VydmljZS5tZW50aW9uU2NvcGU7XG4gICAgdGhpcy5pbnB1dE1vZGUgPSB0aGlzLmNvbmZpZ1NlcnZpY2UuaW5wdXRNb2RlO1xuXG4gICAgdGhpcy5zdWJzY3JpcHRpb25zLnB1c2goXG4gICAgICB0aGlzLnR5cGluZ1N0YXJ0JC5zdWJzY3JpYmUoXG4gICAgICAgICgpID0+IHZvaWQgdGhpcy5jaGFubmVsU2VydmljZS50eXBpbmdTdGFydGVkKHRoaXMucGFyZW50TWVzc2FnZUlkKSxcbiAgICAgICksXG4gICAgKTtcbiAgICB0aGlzLnN1YnNjcmlwdGlvbnMucHVzaChcbiAgICAgIHRoaXMudm9pY2VSZWNvcmRlclNlcnZpY2UuaXNSZWNvcmRlclZpc2libGUkLnN1YnNjcmliZSgoaXNWaXNpYmxlKSA9PiB7XG4gICAgICAgIHRoaXMuaXNWb2ljZVJlY29yZGluZyA9IGlzVmlzaWJsZTtcbiAgICAgIH0pLFxuICAgICk7XG5cbiAgICB0aGlzLnN1YnNjcmlwdGlvbnMucHVzaChcbiAgICAgIGNvbWJpbmVMYXRlc3QoW1xuICAgICAgICB0aGlzLmNoYW5uZWxTZXJ2aWNlLmxhdGVzdE1lc3NhZ2VEYXRlQnlVc2VyQnlDaGFubmVscyQsXG4gICAgICAgIHRoaXMuY2hhbm5lbFNlcnZpY2UuYWN0aXZlQ2hhbm5lbCQsXG4gICAgICBdKVxuICAgICAgICAucGlwZShcbiAgICAgICAgICBtYXAoXG4gICAgICAgICAgICAoW2xhdGVzdE1lc3NhZ2VzLCBjaGFubmVsXSk6IFtcbiAgICAgICAgICAgICAgRGF0ZSB8IHVuZGVmaW5lZCxcbiAgICAgICAgICAgICAgQ2hhbm5lbDxEZWZhdWx0U3RyZWFtQ2hhdEdlbmVyaWNzPiB8IHVuZGVmaW5lZCxcbiAgICAgICAgICAgIF0gPT4gW2xhdGVzdE1lc3NhZ2VzW2NoYW5uZWw/LmNpZCB8fCAnJ10sIGNoYW5uZWwhXSxcbiAgICAgICAgICApLFxuICAgICAgICApXG4gICAgICAgIC5zdWJzY3JpYmUoKFtsYXRlc3RNZXNzYWdlRGF0ZSwgY2hhbm5lbF0pID0+IHtcbiAgICAgICAgICBjb25zdCBjb29sZG93biA9XG4gICAgICAgICAgICAoY2hhbm5lbD8uZGF0YT8uY29vbGRvd24gYXMgbnVtYmVyKSAmJlxuICAgICAgICAgICAgbGF0ZXN0TWVzc2FnZURhdGUgJiZcbiAgICAgICAgICAgIE1hdGgucm91bmQoXG4gICAgICAgICAgICAgIChjaGFubmVsPy5kYXRhPy5jb29sZG93biBhcyBudW1iZXIpIC1cbiAgICAgICAgICAgICAgICAobmV3IERhdGUoKS5nZXRUaW1lKCkgLSBsYXRlc3RNZXNzYWdlRGF0ZS5nZXRUaW1lKCkpIC8gMTAwMCxcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgaWYgKFxuICAgICAgICAgICAgY29vbGRvd24gJiZcbiAgICAgICAgICAgIGNvb2xkb3duID4gMCAmJlxuICAgICAgICAgICAgKGNoYW5uZWw/LmRhdGE/Lm93bl9jYXBhYmlsaXRpZXMgYXMgc3RyaW5nW10pLmluY2x1ZGVzKCdzbG93LW1vZGUnKVxuICAgICAgICAgICkge1xuICAgICAgICAgICAgdGhpcy5zdGFydENvb2xkb3duKGNvb2xkb3duKTtcbiAgICAgICAgICB9IGVsc2UgaWYgKHRoaXMuaXNDb29sZG93bkluUHJvZ3Jlc3MpIHtcbiAgICAgICAgICAgIHRoaXMuc3RvcENvb2xkb3duKCk7XG4gICAgICAgICAgfVxuICAgICAgICB9KSxcbiAgICApO1xuICAgIHRoaXMuc3Vic2NyaXB0aW9ucy5wdXNoKFxuICAgICAgdGhpcy52b2ljZVJlY29yZGVyU2VydmljZS5yZWNvcmRpbmckLnN1YnNjcmliZSgocmVjb3JkaW5nKSA9PiB7XG4gICAgICAgIGlmIChyZWNvcmRpbmcpIHtcbiAgICAgICAgICB2b2lkIHRoaXMudm9pY2VSZWNvcmRpbmdSZWFkeShyZWNvcmRpbmcpO1xuICAgICAgICB9XG4gICAgICB9KSxcbiAgICApO1xuICB9XG5cbiAgbmdPbkNoYW5nZXMoY2hhbmdlczogU2ltcGxlQ2hhbmdlcyk6IHZvaWQge1xuICAgIGlmIChjaGFuZ2VzLm1lc3NhZ2UpIHtcbiAgICAgIHRoaXMubWVzc2FnZVRvVXBkYXRlQ2hhbmdlZCgpO1xuICAgIH1cbiAgICBpZiAoY2hhbmdlcy5pc0ZpbGVVcGxvYWRFbmFibGVkKSB7XG4gICAgICB0aGlzLmNvbmZpZ1NlcnZpY2UuaXNGaWxlVXBsb2FkRW5hYmxlZCA9IHRoaXMuaXNGaWxlVXBsb2FkRW5hYmxlZDtcbiAgICB9XG4gICAgaWYgKGNoYW5nZXMuaXNNdWx0aXBsZUZpbGVVcGxvYWRFbmFibGVkKSB7XG4gICAgICB0aGlzLmNvbmZpZ1NlcnZpY2UuaXNNdWx0aXBsZUZpbGVVcGxvYWRFbmFibGVkID1cbiAgICAgICAgdGhpcy5pc011bHRpcGxlRmlsZVVwbG9hZEVuYWJsZWQ7XG4gICAgfVxuICAgIGlmIChjaGFuZ2VzLmFyZU1lbnRpb25zRW5hYmxlZCkge1xuICAgICAgdGhpcy5jb25maWdTZXJ2aWNlLmFyZU1lbnRpb25zRW5hYmxlZCA9IHRoaXMuYXJlTWVudGlvbnNFbmFibGVkO1xuICAgIH1cbiAgICBpZiAoY2hhbmdlcy5tZW50aW9uU2NvcGUpIHtcbiAgICAgIHRoaXMuY29uZmlnU2VydmljZS5tZW50aW9uU2NvcGUgPSB0aGlzLm1lbnRpb25TY29wZTtcbiAgICB9XG4gICAgaWYgKGNoYW5nZXMubW9kZSkge1xuICAgICAgdGhpcy5zZXRDYW5TZW5kTWVzc2FnZXMoKTtcbiAgICAgIHRoaXMuY2hlY2tJZkluRWRpdE1vZGUoKTtcbiAgICB9XG4gICAgaWYgKGNoYW5nZXMud2F0Y2hGb3JNZXNzYWdlVG9FZGl0KSB7XG4gICAgICB0aGlzLmNoZWNrSWZJbkVkaXRNb2RlKCk7XG4gICAgfVxuICAgIGlmIChjaGFuZ2VzLmlucHV0TW9kZSkge1xuICAgICAgdGhpcy5jb25maWdTZXJ2aWNlLmlucHV0TW9kZSA9IHRoaXMuaW5wdXRNb2RlO1xuICAgIH1cbiAgICBpZiAoY2hhbmdlcy5zZW5kTWVzc2FnZSQpIHtcbiAgICAgIGlmICh0aGlzLnNlbmRNZXNzYWdlU3ViY3JpcHRpb24pIHtcbiAgICAgICAgdGhpcy5zZW5kTWVzc2FnZVN1YmNyaXB0aW9uLnVuc3Vic2NyaWJlKCk7XG4gICAgICB9XG4gICAgICBpZiAodGhpcy5zZW5kTWVzc2FnZSQpIHtcbiAgICAgICAgdGhpcy5zZW5kTWVzc2FnZVN1YmNyaXB0aW9uID0gdGhpcy5zZW5kTWVzc2FnZSQuc3Vic2NyaWJlKFxuICAgICAgICAgICgpID0+IHZvaWQgdGhpcy5tZXNzYWdlU2VudCgpLFxuICAgICAgICApO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIG5nT25Jbml0KCk6IHZvaWQge1xuICAgIHRoaXMuc3Vic2NyaXB0aW9ucy5wdXNoKFxuICAgICAgdGhpcy5jdXN0b21UZW1wbGF0ZXNTZXJ2aWNlLmVtb2ppUGlja2VyVGVtcGxhdGUkLnN1YnNjcmliZSgodGVtcGxhdGUpID0+IHtcbiAgICAgICAgdGhpcy5lbW9qaVBpY2tlclRlbXBsYXRlID0gdGVtcGxhdGU7XG4gICAgICAgIHRoaXMuY2RSZWYuZGV0ZWN0Q2hhbmdlcygpO1xuICAgICAgfSksXG4gICAgKTtcbiAgICB0aGlzLnN1YnNjcmlwdGlvbnMucHVzaChcbiAgICAgIHRoaXMuY3VzdG9tVGVtcGxhdGVzU2VydmljZS5hdHRhY2htZW50UHJldmlld0xpc3RUZW1wbGF0ZSQuc3Vic2NyaWJlKFxuICAgICAgICAodGVtcGxhdGUpID0+IHtcbiAgICAgICAgICB0aGlzLmF0dGFjaG1lbnRQcmV2aWV3TGlzdFRlbXBsYXRlID0gdGVtcGxhdGU7XG4gICAgICAgICAgdGhpcy5jZFJlZi5kZXRlY3RDaGFuZ2VzKCk7XG4gICAgICAgIH0sXG4gICAgICApLFxuICAgICk7XG4gICAgdGhpcy5zdWJzY3JpcHRpb25zLnB1c2goXG4gICAgICB0aGlzLmN1c3RvbVRlbXBsYXRlc1NlcnZpY2UuY3VzdG9tQXR0YWNobWVudFVwbG9hZFRlbXBsYXRlJC5zdWJzY3JpYmUoXG4gICAgICAgICh0ZW1wbGF0ZSkgPT4ge1xuICAgICAgICAgIHRoaXMuY3VzdG9tQXR0YWNobWVudFVwbG9hZFRlbXBsYXRlID0gdGVtcGxhdGU7XG4gICAgICAgICAgdGhpcy5jZFJlZi5kZXRlY3RDaGFuZ2VzKCk7XG4gICAgICAgIH0sXG4gICAgICApLFxuICAgICk7XG4gIH1cblxuICBuZ0FmdGVyVmlld0luaXQoKTogdm9pZCB7XG4gICAgdGhpcy5pc1ZpZXdJbml0ZWQgPSB0cnVlO1xuICAgIHRoaXMuaW5pdFRleHRhcmVhKCk7XG4gIH1cblxuICBuZ09uRGVzdHJveSgpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5zZW5kTWVzc2FnZVN1YmNyaXB0aW9uKSB7XG4gICAgICB0aGlzLnNlbmRNZXNzYWdlU3ViY3JpcHRpb24udW5zdWJzY3JpYmUoKTtcbiAgICB9XG4gICAgdGhpcy5zdWJzY3JpcHRpb25zLmZvckVhY2goKHMpID0+IHMudW5zdWJzY3JpYmUoKSk7XG4gIH1cblxuICBhc3luYyBtZXNzYWdlU2VudCgpIHtcbiAgICBpZiAodGhpcy5pc0Nvb2xkb3duSW5Qcm9ncmVzcykge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBsZXQgYXR0YWNobWVudFVwbG9hZEluUHJvZ3Jlc3NDb3VudGVyITogbnVtYmVyO1xuICAgIHRoaXMuYXR0YWNobWVudFNlcnZpY2UuYXR0YWNobWVudFVwbG9hZEluUHJvZ3Jlc3NDb3VudGVyJFxuICAgICAgLnBpcGUoZmlyc3QoKSlcbiAgICAgIC5zdWJzY3JpYmUoKGNvdW50ZXIpID0+IChhdHRhY2htZW50VXBsb2FkSW5Qcm9ncmVzc0NvdW50ZXIgPSBjb3VudGVyKSk7XG4gICAgaWYgKGF0dGFjaG1lbnRVcGxvYWRJblByb2dyZXNzQ291bnRlciA+IDApIHtcbiAgICAgIGlmICghdGhpcy5oaWRlTm90aWZpY2F0aW9uKSB7XG4gICAgICAgIHRoaXMuaGlkZU5vdGlmaWNhdGlvbiA9XG4gICAgICAgICAgdGhpcy5ub3RpZmljYXRpb25TZXJ2aWNlLmFkZFBlcm1hbmVudE5vdGlmaWNhdGlvbihcbiAgICAgICAgICAgICdzdHJlYW1DaGF0LldhaXQgdW50aWwgYWxsIGF0dGFjaG1lbnRzIGhhdmUgdXBsb2FkZWQnLFxuICAgICAgICAgICk7XG4gICAgICB9XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGNvbnN0IGF0dGFjaG1lbnRzID0gdGhpcy5hdHRhY2htZW50U2VydmljZS5tYXBUb0F0dGFjaG1lbnRzKCk7XG4gICAgbGV0IHRleHQgPSB0aGlzLnRleHRhcmVhVmFsdWU7XG4gICAgdGV4dCA9IHRleHQucmVwbGFjZSgvXlxcbisvZywgJycpOyAvLyBsZWFkaW5nIGVtcHR5IGxpbmVzXG4gICAgdGV4dCA9IHRleHQucmVwbGFjZSgvXFxuKyQvZywgJycpOyAvLyBlbmRpbmcgZW1wdHkgbGluZXNcbiAgICBjb25zdCB0ZXh0Q29udGFpbnNPbmx5U3BhY2VDaGFycyA9ICF0ZXh0LnJlcGxhY2UoLyAvZywgJycpOyAvL3NwY2FlXG4gICAgaWYgKFxuICAgICAgKCF0ZXh0IHx8IHRleHRDb250YWluc09ubHlTcGFjZUNoYXJzKSAmJlxuICAgICAgKCFhdHRhY2htZW50cyB8fCBhdHRhY2htZW50cy5sZW5ndGggPT09IDApXG4gICAgKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGlmICh0ZXh0Q29udGFpbnNPbmx5U3BhY2VDaGFycykge1xuICAgICAgdGV4dCA9ICcnO1xuICAgIH1cbiAgICBpZiAodGhpcy5jb250YWluc0xpbmtzICYmICF0aGlzLmNhblNlbmRMaW5rcykge1xuICAgICAgdGhpcy5ub3RpZmljYXRpb25TZXJ2aWNlLmFkZFRlbXBvcmFyeU5vdGlmaWNhdGlvbihcbiAgICAgICAgJ3N0cmVhbUNoYXQuU2VuZGluZyBsaW5rcyBpcyBub3QgYWxsb3dlZCBpbiB0aGlzIGNvbnZlcnNhdGlvbicsXG4gICAgICApO1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBpZiAoIXRoaXMuaXNVcGRhdGUpIHtcbiAgICAgIHRoaXMudGV4dGFyZWFWYWx1ZSA9ICcnO1xuICAgIH1cbiAgICB0cnkge1xuICAgICAgY29uc3QgbWVzc2FnZSA9IGF3YWl0ICh0aGlzLmlzVXBkYXRlXG4gICAgICAgID8gdGhpcy5jaGFubmVsU2VydmljZS51cGRhdGVNZXNzYWdlKHtcbiAgICAgICAgICAgIC4uLnRoaXMubWVzc2FnZSEsXG4gICAgICAgICAgICB0ZXh0OiB0ZXh0LFxuICAgICAgICAgICAgYXR0YWNobWVudHM6IGF0dGFjaG1lbnRzLFxuICAgICAgICAgIH0pXG4gICAgICAgIDogdGhpcy5jaGFubmVsU2VydmljZS5zZW5kTWVzc2FnZShcbiAgICAgICAgICAgIHRleHQsXG4gICAgICAgICAgICBhdHRhY2htZW50cyxcbiAgICAgICAgICAgIHRoaXMubWVudGlvbmVkVXNlcnMsXG4gICAgICAgICAgICB0aGlzLnBhcmVudE1lc3NhZ2VJZCxcbiAgICAgICAgICAgIHRoaXMucXVvdGVkTWVzc2FnZT8uaWQsXG4gICAgICAgICAgKSk7XG4gICAgICB0aGlzLm1lc3NhZ2VVcGRhdGUuZW1pdCh7IG1lc3NhZ2UgfSk7XG4gICAgICBpZiAodGhpcy5pc1VwZGF0ZSkge1xuICAgICAgICB0aGlzLmRlc2VsZWN0TWVzc2FnZVRvRWRpdCgpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhpcy5hdHRhY2htZW50U2VydmljZS5yZXNldEF0dGFjaG1lbnRVcGxvYWRzKCk7XG4gICAgICB9XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIGlmICh0aGlzLmlzVXBkYXRlKSB7XG4gICAgICAgIHRoaXMubm90aWZpY2F0aW9uU2VydmljZS5hZGRUZW1wb3JhcnlOb3RpZmljYXRpb24oXG4gICAgICAgICAgJ3N0cmVhbUNoYXQuRWRpdCBtZXNzYWdlIHJlcXVlc3QgZmFpbGVkJyxcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICB9XG4gICAgdm9pZCB0aGlzLmNoYW5uZWxTZXJ2aWNlLnR5cGluZ1N0b3BwZWQodGhpcy5wYXJlbnRNZXNzYWdlSWQpO1xuICAgIGlmICh0aGlzLnF1b3RlZE1lc3NhZ2UpIHtcbiAgICAgIHRoaXMuZGVzZWxlY3RNZXNzYWdlVG9RdW90ZSgpO1xuICAgIH1cbiAgfVxuXG4gIGdldCBjb250YWluc0xpbmtzKCkge1xuICAgIHJldHVybiAvKD86KD86aHR0cHM/fGZ0cCk6XFwvXFwvKT9bXFx3L1xcLT89JS5dK1xcLltcXHcvXFwtJj89JS5dKy8udGVzdChcbiAgICAgIHRoaXMudGV4dGFyZWFWYWx1ZSxcbiAgICApO1xuICB9XG5cbiAgZ2V0IHF1b3RlZE1lc3NhZ2VBdHRhY2htZW50cygpIHtcbiAgICBjb25zdCBvcmlnaW5hbEF0dGFjaG1lbnRzID0gdGhpcy5xdW90ZWRNZXNzYWdlPy5hdHRhY2htZW50cztcbiAgICByZXR1cm4gb3JpZ2luYWxBdHRhY2htZW50cyAmJiBvcmlnaW5hbEF0dGFjaG1lbnRzLmxlbmd0aFxuICAgICAgPyBbb3JpZ2luYWxBdHRhY2htZW50c1swXV1cbiAgICAgIDogW107XG4gIH1cblxuICBnZXQgZGlzYWJsZWRUZXh0YXJlYVRleHQoKSB7XG4gICAgaWYgKCF0aGlzLmNhblNlbmRNZXNzYWdlcykge1xuICAgICAgcmV0dXJuIHRoaXMubW9kZSA9PT0gJ3RocmVhZCdcbiAgICAgICAgPyBcInN0cmVhbUNoYXQuWW91IGNhbid0IHNlbmQgdGhyZWFkIHJlcGxpZXMgaW4gdGhpcyBjaGFubmVsXCJcbiAgICAgICAgOiBcInN0cmVhbUNoYXQuWW91IGNhbid0IHNlbmQgbWVzc2FnZXMgaW4gdGhpcyBjaGFubmVsXCI7XG4gICAgfVxuICAgIHJldHVybiAnJztcbiAgfVxuXG4gIGl0ZW1zUGFzdGVkKGV2ZW50OiBDbGlwYm9hcmRFdmVudCkge1xuICAgIGlmICh0aGlzLmNvbmZpZ1NlcnZpY2UuY3VzdG9tUGFzdGVFdmVudEhhbmRsZXIpIHtcbiAgICAgIHRoaXMuY29uZmlnU2VydmljZS5jdXN0b21QYXN0ZUV2ZW50SGFuZGxlcihldmVudCwgdGhpcyk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGlmIChldmVudC5jbGlwYm9hcmREYXRhPy5maWxlcyAmJiBldmVudC5jbGlwYm9hcmREYXRhPy5maWxlcy5sZW5ndGggPiAwKSB7XG4gICAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgIHZvaWQgdGhpcy5maWxlc1NlbGVjdGVkKGV2ZW50LmNsaXBib2FyZERhdGE/LmZpbGVzKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBhc3luYyBmaWxlc1NlbGVjdGVkKGZpbGVMaXN0OiBGaWxlTGlzdCB8IG51bGwpIHtcbiAgICBhd2FpdCB0aGlzLmF0dGFjaG1lbnRTZXJ2aWNlLmZpbGVzU2VsZWN0ZWQoZmlsZUxpc3QpO1xuICAgIHRoaXMuY2xlYXJGaWxlSW5wdXQoKTtcbiAgfVxuXG4gIGRlc2VsZWN0TWVzc2FnZVRvUXVvdGUoKSB7XG4gICAgdGhpcy5jaGFubmVsU2VydmljZS5zZWxlY3RNZXNzYWdlVG9RdW90ZSh1bmRlZmluZWQpO1xuICB9XG5cbiAgZGVzZWxlY3RNZXNzYWdlVG9FZGl0KCkge1xuICAgIHRoaXMubWVzc2FnZUFjdGlvbnNTZXJ2aWNlLm1lc3NhZ2VUb0VkaXQkLm5leHQodW5kZWZpbmVkKTtcbiAgfVxuXG4gIGdldEVtb2ppUGlja2VyQ29udGV4dCgpOiBFbW9qaVBpY2tlckNvbnRleHQge1xuICAgIHJldHVybiB7XG4gICAgICBlbW9qaUlucHV0JDogdGhpcy5lbW9qaUlucHV0U2VydmljZS5lbW9qaUlucHV0JCxcbiAgICB9O1xuICB9XG5cbiAgZ2V0QXR0YWNobWVudFByZXZpZXdMaXN0Q29udGV4dCgpOiBBdHRhY2htZW50UHJldmlld0xpc3RDb250ZXh0IHtcbiAgICByZXR1cm4ge1xuICAgICAgYXR0YWNobWVudFVwbG9hZHMkOiB0aGlzLmF0dGFjaG1lbnRTZXJ2aWNlLmF0dGFjaG1lbnRVcGxvYWRzJCxcbiAgICAgIGRlbGV0ZVVwbG9hZEhhbmRsZXI6IHRoaXMuZGVsZXRlVXBsb2FkLmJpbmQodGhpcyksXG4gICAgICByZXRyeVVwbG9hZEhhbmRsZXI6IHRoaXMucmV0cnlVcGxvYWQuYmluZCh0aGlzKSxcbiAgICAgIHNlcnZpY2U6IHRoaXMuYXR0YWNobWVudFNlcnZpY2UsXG4gICAgfTtcbiAgfVxuXG4gIGdldEF0dGFjaG1lbnRVcGxvYWRDb250ZXh0KCk6IEN1c3RvbUF0dGFjaG1lbnRVcGxvYWRDb250ZXh0IHtcbiAgICByZXR1cm4ge1xuICAgICAgaXNNdWx0aXBsZUZpbGVVcGxvYWRFbmFibGVkOiB0aGlzLmlzTXVsdGlwbGVGaWxlVXBsb2FkRW5hYmxlZCxcbiAgICAgIGF0dGFjaG1lbnRTZXJ2aWNlOiB0aGlzLmF0dGFjaG1lbnRTZXJ2aWNlLFxuICAgIH07XG4gIH1cblxuICBnZXRRdW90ZWRNZXNzYWdlVGV4dENvbnRleHQoKTogTWVzc2FnZVRleHRDb250ZXh0IHtcbiAgICByZXR1cm4ge1xuICAgICAgbWVzc2FnZTogdGhpcy5xdW90ZWRNZXNzYWdlLFxuICAgICAgaXNRdW90ZWQ6IHRydWUsXG4gICAgICBzaG91bGRUcmFuc2xhdGU6IHRydWUsXG4gICAgfTtcbiAgfVxuXG4gIGFzeW5jIHN0YXJ0Vm9pY2VSZWNvcmRpbmcoKSB7XG4gICAgYXdhaXQgdGhpcy5hdWRpb1JlY29yZGVyPy5zdGFydCgpO1xuICAgIGlmICh0aGlzLmF1ZGlvUmVjb3JkZXI/LmlzUmVjb3JkaW5nKSB7XG4gICAgICB0aGlzLnZvaWNlUmVjb3JkZXJTZXJ2aWNlLmlzUmVjb3JkZXJWaXNpYmxlJC5uZXh0KHRydWUpO1xuICAgIH1cbiAgfVxuXG4gIGFzeW5jIHZvaWNlUmVjb3JkaW5nUmVhZHkocmVjb3JkaW5nOiBBdWRpb1JlY29yZGluZykge1xuICAgIHRyeSB7XG4gICAgICBhd2FpdCB0aGlzLmF0dGFjaG1lbnRTZXJ2aWNlLnVwbG9hZFZvaWNlUmVjb3JkaW5nKHJlY29yZGluZyk7XG4gICAgICBpZiAodGhpcy5jb25maWdTZXJ2aWNlLnNlbmRWb2ljZVJlY29yZGluZ0ltbWVkaWF0ZWx5KSB7XG4gICAgICAgIGF3YWl0IHRoaXMubWVzc2FnZVNlbnQoKTtcbiAgICAgIH1cbiAgICB9IGZpbmFsbHkge1xuICAgICAgdGhpcy52b2ljZVJlY29yZGVyU2VydmljZS5pc1JlY29yZGVyVmlzaWJsZSQubmV4dChmYWxzZSk7XG4gICAgfVxuICB9XG5cbiAgZ2V0IGlzVXBkYXRlKCkge1xuICAgIHJldHVybiAhIXRoaXMubWVzc2FnZTtcbiAgfVxuXG4gIHByaXZhdGUgZGVsZXRlVXBsb2FkKHVwbG9hZDogQXR0YWNobWVudFVwbG9hZCkge1xuICAgIGlmICh0aGlzLmlzVXBkYXRlKSB7XG4gICAgICAvLyBEZWxheSBkZWxldGUgdG8gYXZvaWQgbW9kYWwgZGV0ZWN0aW5nIHRoaXMgY2xpY2sgYXMgb3V0c2lkZSBjbGlja1xuICAgICAgc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICAgIHZvaWQgdGhpcy5hdHRhY2htZW50U2VydmljZS5kZWxldGVBdHRhY2htZW50KHVwbG9hZCk7XG4gICAgICB9KTtcbiAgICB9IGVsc2Uge1xuICAgICAgdm9pZCB0aGlzLmF0dGFjaG1lbnRTZXJ2aWNlLmRlbGV0ZUF0dGFjaG1lbnQodXBsb2FkKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIHJldHJ5VXBsb2FkKGZpbGU6IEZpbGUpIHtcbiAgICB2b2lkIHRoaXMuYXR0YWNobWVudFNlcnZpY2UucmV0cnlBdHRhY2htZW50VXBsb2FkKGZpbGUpO1xuICB9XG5cbiAgcHJpdmF0ZSBjbGVhckZpbGVJbnB1dCgpIHtcbiAgICB0aGlzLmZpbGVJbnB1dC5uYXRpdmVFbGVtZW50LnZhbHVlID0gJyc7XG4gIH1cblxuICBwcml2YXRlIGluaXRUZXh0YXJlYSgpIHtcbiAgICAvLyBjbGVhbnVwIHByZXZpb3VzbHkgYnVpbHQgdGV4dGFyZWFcbiAgICBpZiAoIXRoaXMuY2FuU2VuZE1lc3NhZ2VzKSB7XG4gICAgICB0aGlzLnRleHRhcmVhUmVmID0gdW5kZWZpbmVkO1xuICAgIH1cblxuICAgIGlmICghdGhpcy5jYW5TZW5kTWVzc2FnZXMgfHwgdGhpcy50ZXh0YXJlYVJlZiB8fCAhdGhpcy50ZXh0YXJlYUFuY2hvcikge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNvbnN0IGNvbXBvbmVudEZhY3RvcnkgPVxuICAgICAgdGhpcy5jb21wb25lbnRGYWN0b3J5UmVzb2x2ZXIucmVzb2x2ZUNvbXBvbmVudEZhY3RvcnkodGhpcy50ZXh0YXJlYVR5cGUpO1xuICAgIHRoaXMudGV4dGFyZWFSZWYgPVxuICAgICAgdGhpcy50ZXh0YXJlYUFuY2hvci52aWV3Q29udGFpbmVyUmVmLmNyZWF0ZUNvbXBvbmVudDxUZXh0YXJlYUludGVyZmFjZT4oXG4gICAgICAgIGNvbXBvbmVudEZhY3RvcnksXG4gICAgICApO1xuICAgIHRoaXMuY2RSZWYuZGV0ZWN0Q2hhbmdlcygpO1xuICB9XG5cbiAgcHJpdmF0ZSBzZXRDYW5TZW5kTWVzc2FnZXMoKSB7XG4gICAgY29uc3QgY2FwYWJpbGl0aWVzID0gdGhpcy5jaGFubmVsPy5kYXRhPy5vd25fY2FwYWJpbGl0aWVzIGFzIHN0cmluZ1tdO1xuICAgIGlmICghY2FwYWJpbGl0aWVzKSB7XG4gICAgICB0aGlzLmNhblNlbmRNZXNzYWdlcyA9IGZhbHNlO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLmNhblNlbmRNZXNzYWdlcyA9XG4gICAgICAgIGNhcGFiaWxpdGllcy5pbmRleE9mKFxuICAgICAgICAgIHRoaXMubW9kZSA9PT0gJ21haW4nID8gJ3NlbmQtbWVzc2FnZScgOiAnc2VuZC1yZXBseScsXG4gICAgICAgICkgIT09IC0xIHx8IHRoaXMuaXNVcGRhdGU7XG4gICAgfVxuICAgIGlmICh0aGlzLmlzVmlld0luaXRlZCkge1xuICAgICAgdGhpcy5jZFJlZi5kZXRlY3RDaGFuZ2VzKCk7XG4gICAgICB0aGlzLmluaXRUZXh0YXJlYSgpO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgZ2V0IHBhcmVudE1lc3NhZ2VJZCgpIHtcbiAgICBsZXQgcGFyZW50TWVzc2FnZUlkOiBzdHJpbmcgfCB1bmRlZmluZWQgPSB1bmRlZmluZWQ7XG4gICAgaWYgKHRoaXMubW9kZSA9PT0gJ3RocmVhZCcpIHtcbiAgICAgIHRoaXMuY2hhbm5lbFNlcnZpY2UuYWN0aXZlUGFyZW50TWVzc2FnZUlkJFxuICAgICAgICAucGlwZShmaXJzdCgpKVxuICAgICAgICAuc3Vic2NyaWJlKChpZCkgPT4gKHBhcmVudE1lc3NhZ2VJZCA9IGlkKSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHBhcmVudE1lc3NhZ2VJZDtcbiAgfVxuXG4gIHByaXZhdGUgc3RhcnRDb29sZG93bihjb29sZG93bjogbnVtYmVyKSB7XG4gICAgdGhpcy50ZXh0YXJlYVBsYWNlaG9sZGVyID0gdGhpcy5zbG93TW9kZVRleHRhcmVhUGxhY2Vob2xkZXI7XG4gICAgdGhpcy5pc0Nvb2xkb3duSW5Qcm9ncmVzcyA9IHRydWU7XG4gICAgdGhpcy5jb29sZG93biQgPSB0aW1lcigwLCAxMDAwKS5waXBlKFxuICAgICAgdGFrZShjb29sZG93biArIDEpLFxuICAgICAgbWFwKCh2KSA9PiBjb29sZG93biAtIHYpLFxuICAgICAgdGFwKCh2KSA9PiB7XG4gICAgICAgIGlmICh2ID09PSAwKSB7XG4gICAgICAgICAgdGhpcy5zdG9wQ29vbGRvd24oKTtcbiAgICAgICAgfVxuICAgICAgfSksXG4gICAgKTtcbiAgfVxuXG4gIHByaXZhdGUgc3RvcENvb2xkb3duKCkge1xuICAgIHRoaXMuY29vbGRvd24kID0gdW5kZWZpbmVkO1xuICAgIHRoaXMuaXNDb29sZG93bkluUHJvZ3Jlc3MgPSBmYWxzZTtcbiAgICB0aGlzLnRleHRhcmVhUGxhY2Vob2xkZXIgPSB0aGlzLmRlZmF1bHRUZXh0YXJlYVBsYWNlaG9sZGVyO1xuICB9XG5cbiAgcHJpdmF0ZSBjaGVja0lmSW5FZGl0TW9kZSgpIHtcbiAgICBpZiAoIXRoaXMud2F0Y2hGb3JNZXNzYWdlVG9FZGl0KSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGlmICghdGhpcy5tZXNzYWdlVG9FZGl0ICYmIHRoaXMubWVzc2FnZSkge1xuICAgICAgdGhpcy5tZXNzYWdlID0gdW5kZWZpbmVkO1xuICAgICAgdGhpcy5tZXNzYWdlVG9VcGRhdGVDaGFuZ2VkKCk7XG4gICAgICBpZiAodGhpcy5pc1ZpZXdJbml0ZWQpIHtcbiAgICAgICAgdGhpcy5jZFJlZi5kZXRlY3RDaGFuZ2VzKCk7XG4gICAgICB9XG4gICAgfVxuICAgIGlmIChcbiAgICAgIHRoaXMubWVzc2FnZVRvRWRpdCAmJlxuICAgICAgKCh0aGlzLm1vZGUgPT09ICdtYWluJyAmJiAhdGhpcy5tZXNzYWdlVG9FZGl0LnBhcmVudF9pZCkgfHxcbiAgICAgICAgKHRoaXMubW9kZSA9PT0gJ3RocmVhZCcgJiYgdGhpcy5tZXNzYWdlVG9FZGl0LnBhcmVudF9pZCkpXG4gICAgKSB7XG4gICAgICB0aGlzLm1lc3NhZ2UgPSB0aGlzLm1lc3NhZ2VUb0VkaXQ7XG4gICAgICB0aGlzLm1lc3NhZ2VUb1VwZGF0ZUNoYW5nZWQoKTtcbiAgICAgIGlmICh0aGlzLmlzVmlld0luaXRlZCkge1xuICAgICAgICB0aGlzLmNkUmVmLmRldGVjdENoYW5nZXMoKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBwcml2YXRlIG1lc3NhZ2VUb1VwZGF0ZUNoYW5nZWQoKSB7XG4gICAgdGhpcy5hdHRhY2htZW50U2VydmljZS5yZXNldEF0dGFjaG1lbnRVcGxvYWRzKCk7XG4gICAgdGhpcy5zZXRDYW5TZW5kTWVzc2FnZXMoKTtcbiAgICBpZiAodGhpcy5pc1VwZGF0ZSkge1xuICAgICAgdGhpcy5hdHRhY2htZW50U2VydmljZS5jcmVhdGVGcm9tQXR0YWNobWVudHMoXG4gICAgICAgIHRoaXMubWVzc2FnZSEuYXR0YWNobWVudHMgfHwgW10sXG4gICAgICApO1xuICAgICAgdGhpcy50ZXh0YXJlYVZhbHVlID0gdGhpcy5tZXNzYWdlIS50ZXh0IHx8ICcnO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLnRleHRhcmVhVmFsdWUgPSAnJztcbiAgICB9XG4gIH1cbn1cbiIsIjxkaXZcbiAgY2xhc3M9XCJzdHItY2hhdF9fbWVzc2FnZS1pbnB1dCBzdHItY2hhdC1hbmd1bGFyX19tZXNzYWdlLWlucHV0XCJcbiAgW3N0eWxlLmRpc3BsYXldPVwiaXNWb2ljZVJlY29yZGluZyA/ICdub25lJyA6ICdmbGV4J1wiXG4+XG4gIEBpZiAocXVvdGVkTWVzc2FnZSkge1xuICAgIDxkaXYgY2xhc3M9XCJzdHItY2hhdF9fcXVvdGVkLW1lc3NhZ2UtcHJldmlldy1oZWFkZXJcIj5cbiAgICAgIDxkaXYgY2xhc3M9XCJzdHItY2hhdF9fcXVvdGVkLW1lc3NhZ2UtcmVwbHktdG8tbWVzc2FnZVwiPlxuICAgICAgICB7eyBcInN0cmVhbUNoYXQuUmVwbHkgdG8gTWVzc2FnZVwiIHwgdHJhbnNsYXRlIH19XG4gICAgICA8L2Rpdj5cbiAgICAgIDxidXR0b25cbiAgICAgICAgY2xhc3M9XCJzdHItY2hhdF9fcXVvdGVkLW1lc3NhZ2UtcmVtb3ZlXCJcbiAgICAgICAgZGF0YS10ZXN0aWQ9XCJyZW1vdmUtcXVvdGVcIlxuICAgICAgICAoY2xpY2spPVwiZGVzZWxlY3RNZXNzYWdlVG9RdW90ZSgpXCJcbiAgICAgICAgKGtleXVwLmVudGVyKT1cImRlc2VsZWN0TWVzc2FnZVRvUXVvdGUoKVwiXG4gICAgICA+XG4gICAgICAgIDxzdHJlYW0taWNvbi1wbGFjZWhvbGRlciBpY29uPVwiY2xvc2VcIiAvPlxuICAgICAgPC9idXR0b24+XG4gICAgPC9kaXY+XG4gIH1cbiAgQGlmIChpc1VwZGF0ZSkge1xuICAgIDxkaXYgY2xhc3M9XCJzdHItY2hhdF9fcXVvdGVkLW1lc3NhZ2UtcHJldmlldy1oZWFkZXJcIj5cbiAgICAgIDxkaXYgY2xhc3M9XCJzdHItY2hhdF9fcXVvdGVkLW1lc3NhZ2UtcmVwbHktdG8tbWVzc2FnZVwiPlxuICAgICAgICB7eyBcInN0cmVhbUNoYXQuRWRpdCBNZXNzYWdlXCIgfCB0cmFuc2xhdGUgfX1cbiAgICAgIDwvZGl2PlxuICAgICAgPGJ1dHRvblxuICAgICAgICBjbGFzcz1cInN0ci1jaGF0X19xdW90ZWQtbWVzc2FnZS1yZW1vdmVcIlxuICAgICAgICBkYXRhLXRlc3RpZD1cInJlbW92ZS1xdW90ZVwiXG4gICAgICAgIChjbGljayk9XCJkZXNlbGVjdE1lc3NhZ2VUb0VkaXQoKVwiXG4gICAgICAgIChrZXl1cC5lbnRlcik9XCJkZXNlbGVjdE1lc3NhZ2VUb0VkaXQoKVwiXG4gICAgICA+XG4gICAgICAgIDxzdHJlYW0taWNvbi1wbGFjZWhvbGRlciBpY29uPVwiY2xvc2VcIiAvPlxuICAgICAgPC9idXR0b24+XG4gICAgPC9kaXY+XG4gIH1cbiAgQGlmIChjYW5TZW5kTWVzc2FnZXMpIHtcbiAgICA8ZGl2XG4gICAgICBjbGFzcz1cInN0ci1jaGF0X19tZXNzYWdlLWlucHV0LWlubmVyIHN0ci1jaGF0LWFuZ3VsYXJfX21lc3NhZ2UtaW5wdXQtaW5uZXJcIlxuICAgID5cbiAgICAgIDxuZy1jb250ZW50IHNlbGVjdD1cIlttZXNzYWdlLWlucHV0LXN0YXJ0XVwiIC8+XG4gICAgICBAaWYgKGlzRmlsZVVwbG9hZEVuYWJsZWQgJiYgaXNGaWxlVXBsb2FkQXV0aG9yaXplZCAmJiBjYW5TZW5kTWVzc2FnZXMpIHtcbiAgICAgICAgPG5nLWNvbnRhaW5lclxuICAgICAgICAgICpuZ1RlbXBsYXRlT3V0bGV0PVwiXG4gICAgICAgICAgICBjdXN0b21BdHRhY2htZW50VXBsb2FkVGVtcGxhdGUgfHwgZGVmYXVsdEF0dGFjaG1lbnRVcGxvYWQ7XG4gICAgICAgICAgICBjb250ZXh0OiBnZXRBdHRhY2htZW50VXBsb2FkQ29udGV4dCgpXG4gICAgICAgICAgXCJcbiAgICAgICAgLz5cbiAgICAgICAgPG5nLXRlbXBsYXRlICNkZWZhdWx0QXR0YWNobWVudFVwbG9hZD5cbiAgICAgICAgICA8ZGl2XG4gICAgICAgICAgICBjbGFzcz1cInN0ci1jaGF0X19maWxlLWlucHV0LWNvbnRhaW5lclwiXG4gICAgICAgICAgICBkYXRhLXRlc3RpZD1cImZpbGUtdXBsb2FkLWJ1dHRvblwiXG4gICAgICAgICAgPlxuICAgICAgICAgICAgPGlucHV0XG4gICAgICAgICAgICAgICNmaWxlSW5wdXRcbiAgICAgICAgICAgICAgdHlwZT1cImZpbGVcIlxuICAgICAgICAgICAgICBjbGFzcz1cInN0ci1jaGF0X19maWxlLWlucHV0XCJcbiAgICAgICAgICAgICAgZGF0YS10ZXN0aWQ9XCJmaWxlLWlucHV0XCJcbiAgICAgICAgICAgICAgW211bHRpcGxlXT1cImlzTXVsdGlwbGVGaWxlVXBsb2FkRW5hYmxlZFwiXG4gICAgICAgICAgICAgIGlkPVwie3sgZmlsZUlucHV0SWQgfX1cIlxuICAgICAgICAgICAgICBbZGlzYWJsZWRdPVwiXG4gICAgICAgICAgICAgICAgKGF0dGFjaG1lbnRTZXJ2aWNlLmF0dGFjaG1lbnRzQ291bnRlciQgfCBhc3luYykhID49XG4gICAgICAgICAgICAgICAgYXR0YWNobWVudFNlcnZpY2UubWF4TnVtYmVyT2ZBdHRhY2htZW50c1xuICAgICAgICAgICAgICBcIlxuICAgICAgICAgICAgICAoY2hhbmdlKT1cImZpbGVzU2VsZWN0ZWQoZmlsZUlucHV0LmZpbGVzKVwiXG4gICAgICAgICAgICAvPlxuICAgICAgICAgICAgPGxhYmVsIGNsYXNzPVwic3RyLWNoYXRfX2ZpbGUtaW5wdXQtbGFiZWxcIiBmb3I9XCJ7eyBmaWxlSW5wdXRJZCB9fVwiPlxuICAgICAgICAgICAgICA8c3RyZWFtLWljb24tcGxhY2Vob2xkZXIgaWNvbj1cImF0dGFjaFwiIC8+XG4gICAgICAgICAgICA8L2xhYmVsPlxuICAgICAgICAgIDwvZGl2PlxuICAgICAgICA8L25nLXRlbXBsYXRlPlxuICAgICAgfVxuICAgICAgPGRpdiBjbGFzcz1cInN0ci1jaGF0X19tZXNzYWdlLXRleHRhcmVhLWNvbnRhaW5lclwiPlxuICAgICAgICBAaWYgKHF1b3RlZE1lc3NhZ2UpIHtcbiAgICAgICAgICA8ZGl2XG4gICAgICAgICAgICBkYXRhLXRlc3RpZD1cInF1b3RlZC1tZXNzYWdlLWNvbnRhaW5lclwiXG4gICAgICAgICAgICBjbGFzcz1cInN0ci1jaGF0X19xdW90ZWQtbWVzc2FnZS1wcmV2aWV3XCJcbiAgICAgICAgICA+XG4gICAgICAgICAgICA8c3RyZWFtLWF2YXRhci1wbGFjZWhvbGRlclxuICAgICAgICAgICAgICBkYXRhLXRlc3RpZD1cInFvdXRlZC1tZXNzYWdlLWF2YXRhclwiXG4gICAgICAgICAgICAgIGNsYXNzPVwic3RyLWNoYXQtYW5ndWxhcl9fYXZhdGFyLWhvc3Qgc3RyLWNoYXRfX21lc3NhZ2Utc2VuZGVyLWF2YXRhclwiXG4gICAgICAgICAgICAgIHR5cGU9XCJ1c2VyXCJcbiAgICAgICAgICAgICAgbG9jYXRpb249XCJxdW90ZWQtbWVzc2FnZS1zZW5kZXJcIlxuICAgICAgICAgICAgICBbaW1hZ2VVcmxdPVwicXVvdGVkTWVzc2FnZS51c2VyPy5pbWFnZVwiXG4gICAgICAgICAgICAgIFtuYW1lXT1cInF1b3RlZE1lc3NhZ2UudXNlcj8ubmFtZSB8fCBxdW90ZWRNZXNzYWdlLnVzZXI/LmlkXCJcbiAgICAgICAgICAgICAgW3VzZXJdPVwicXVvdGVkTWVzc2FnZS51c2VyIHx8IHVuZGVmaW5lZFwiXG4gICAgICAgICAgICAvPlxuICAgICAgICAgICAgPGRpdlxuICAgICAgICAgICAgICBjbGFzcz1cInF1b3RlZC1tZXNzYWdlLXByZXZpZXctY29udGVudC1pbm5lciBzdHItY2hhdF9fcXVvdGVkLW1lc3NhZ2UtYnViYmxlXCJcbiAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgQGlmIChcbiAgICAgICAgICAgICAgICBxdW90ZWRNZXNzYWdlLmF0dGFjaG1lbnRzICYmIHF1b3RlZE1lc3NhZ2UuYXR0YWNobWVudHMubGVuZ3RoXG4gICAgICAgICAgICAgICkge1xuICAgICAgICAgICAgICAgIDxzdHJlYW0tYXR0YWNobWVudC1saXN0XG4gICAgICAgICAgICAgICAgICBbYXR0YWNobWVudHNdPVwicXVvdGVkTWVzc2FnZUF0dGFjaG1lbnRzXCJcbiAgICAgICAgICAgICAgICAgIFttZXNzYWdlSWRdPVwicXVvdGVkTWVzc2FnZS5pZFwiXG4gICAgICAgICAgICAgICAgLz5cbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwic3RyLWNoYXRfX3F1b3RlZC1tZXNzYWdlLXRleHRcIj5cbiAgICAgICAgICAgICAgICA8bmctY29udGFpbmVyXG4gICAgICAgICAgICAgICAgICAqbmdUZW1wbGF0ZU91dGxldD1cIlxuICAgICAgICAgICAgICAgICAgICAoY3VzdG9tVGVtcGxhdGVzU2VydmljZS5tZXNzYWdlVGV4dFRlbXBsYXRlJCB8IGFzeW5jKSB8fFxuICAgICAgICAgICAgICAgICAgICAgIGRlZmF1bHRUZXh0O1xuICAgICAgICAgICAgICAgICAgICBjb250ZXh0OiBnZXRRdW90ZWRNZXNzYWdlVGV4dENvbnRleHQoKVxuICAgICAgICAgICAgICAgICAgXCJcbiAgICAgICAgICAgICAgICAvPlxuICAgICAgICAgICAgICAgIDxuZy10ZW1wbGF0ZVxuICAgICAgICAgICAgICAgICAgI2RlZmF1bHRUZXh0XG4gICAgICAgICAgICAgICAgICBsZXQtbWVzc2FnZT1cIm1lc3NhZ2VcIlxuICAgICAgICAgICAgICAgICAgbGV0LWlzUXVvdGVkPVwiaXNRdW90ZWRcIlxuICAgICAgICAgICAgICAgICAgbGV0LXNob3VsZFRyYW5zbGF0ZT1cInNob3VsZFRyYW5zbGF0ZVwiXG4gICAgICAgICAgICAgICAgPlxuICAgICAgICAgICAgICAgICAgPHN0cmVhbS1tZXNzYWdlLXRleHRcbiAgICAgICAgICAgICAgICAgICAgW21lc3NhZ2VdPVwibWVzc2FnZVwiXG4gICAgICAgICAgICAgICAgICAgIFtpc1F1b3RlZF09XCJpc1F1b3RlZFwiXG4gICAgICAgICAgICAgICAgICAgIFtzaG91bGRUcmFuc2xhdGVdPVwic2hvdWxkVHJhbnNsYXRlXCJcbiAgICAgICAgICAgICAgICAgICAgZGF0YS10ZXN0aWQ9XCJxdW90ZWQtbWVzc2FnZS10ZXh0XCJcbiAgICAgICAgICAgICAgICAgIC8+XG4gICAgICAgICAgICAgICAgPC9uZy10ZW1wbGF0ZT5cbiAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgfVxuICAgICAgICA8bmctdGVtcGxhdGVcbiAgICAgICAgICAjZGVmYXVsdEF0dGFjaG1lbnRzUHJldmlld1xuICAgICAgICAgIGxldC1hdHRhY2htZW50VXBsb2FkcyQ9XCJhdHRhY2htZW50VXBsb2FkcyRcIlxuICAgICAgICAgIGxldC1yZXRyeVVwbG9hZEhhbmRsZXI9XCJyZXRyeVVwbG9hZEhhbmRsZXJcIlxuICAgICAgICAgIGxldC1kZWxldGVVcGxvYWRIYW5kbGVyPVwiZGVsZXRlVXBsb2FkSGFuZGxlclwiXG4gICAgICAgID5cbiAgICAgICAgICA8c3RyZWFtLWF0dGFjaG1lbnQtcHJldmlldy1saXN0XG4gICAgICAgICAgICBjbGFzcz1cInN0ci1jaGF0X19hdHRhY2htZW50LXByZXZpZXctbGlzdC1hbmd1bGFyLWhvc3RcIlxuICAgICAgICAgICAgW2F0dGFjaG1lbnRVcGxvYWRzJF09XCJhdHRhY2htZW50VXBsb2FkcyRcIlxuICAgICAgICAgICAgKHJldHJ5QXR0YWNobWVudFVwbG9hZCk9XCJyZXRyeVVwbG9hZEhhbmRsZXIoJGV2ZW50KVwiXG4gICAgICAgICAgICAoZGVsZXRlQXR0YWNobWVudCk9XCJkZWxldGVVcGxvYWRIYW5kbGVyKCRldmVudClcIlxuICAgICAgICAgIC8+XG4gICAgICAgIDwvbmctdGVtcGxhdGU+XG4gICAgICAgIDxuZy1jb250YWluZXJcbiAgICAgICAgICAqbmdUZW1wbGF0ZU91dGxldD1cIlxuICAgICAgICAgICAgYXR0YWNobWVudFByZXZpZXdMaXN0VGVtcGxhdGUgfHwgZGVmYXVsdEF0dGFjaG1lbnRzUHJldmlldztcbiAgICAgICAgICAgIGNvbnRleHQ6IGdldEF0dGFjaG1lbnRQcmV2aWV3TGlzdENvbnRleHQoKVxuICAgICAgICAgIFwiXG4gICAgICAgIC8+XG4gICAgICAgIDxkaXYgY2xhc3M9XCJzdHItY2hhdF9fbWVzc2FnZS10ZXh0YXJlYS13aXRoLWVtb2ppLXBpY2tlclwiPlxuICAgICAgICAgIDxuZy1jb250YWluZXJcbiAgICAgICAgICAgIHN0cmVhbVRleHRhcmVhXG4gICAgICAgICAgICBbY29tcG9uZW50UmVmXT1cInRleHRhcmVhUmVmXCJcbiAgICAgICAgICAgIFthcmVNZW50aW9uc0VuYWJsZWRdPVwiYXJlTWVudGlvbnNFbmFibGVkXCJcbiAgICAgICAgICAgIFttZW50aW9uU2NvcGVdPVwibWVudGlvblNjb3BlXCJcbiAgICAgICAgICAgIFtpbnB1dE1vZGVdPVwiaW5wdXRNb2RlXCJcbiAgICAgICAgICAgIFthdXRvRm9jdXNdPVwiYXV0b0ZvY3VzXCJcbiAgICAgICAgICAgIFtwbGFjZWhvbGRlcl09XCJ0ZXh0YXJlYVBsYWNlaG9sZGVyXCJcbiAgICAgICAgICAgIFsodmFsdWUpXT1cInRleHRhcmVhVmFsdWVcIlxuICAgICAgICAgICAgKHZhbHVlQ2hhbmdlKT1cInR5cGluZ1N0YXJ0JC5uZXh0KClcIlxuICAgICAgICAgICAgKHNlbmQpPVwibWVzc2FnZVNlbnQoKVwiXG4gICAgICAgICAgICAodXNlck1lbnRpb25zKT1cIm1lbnRpb25lZFVzZXJzID0gJGV2ZW50XCJcbiAgICAgICAgICAgIChwYXN0ZUZyb21DbGlwYm9hcmQpPVwiaXRlbXNQYXN0ZWQoJGV2ZW50KVwiXG4gICAgICAgICAgLz5cbiAgICAgICAgICBAaWYgKGVtb2ppUGlja2VyVGVtcGxhdGUpIHtcbiAgICAgICAgICAgIDxuZy1jb250YWluZXJcbiAgICAgICAgICAgICAgKm5nVGVtcGxhdGVPdXRsZXQ9XCJcbiAgICAgICAgICAgICAgICBlbW9qaVBpY2tlclRlbXBsYXRlO1xuICAgICAgICAgICAgICAgIGNvbnRleHQ6IGdldEVtb2ppUGlja2VyQ29udGV4dCgpXG4gICAgICAgICAgICAgIFwiXG4gICAgICAgICAgICAvPlxuICAgICAgICAgIH1cbiAgICAgICAgPC9kaXY+XG4gICAgICA8L2Rpdj5cbiAgICAgIEBpZiAoY2FuU2VuZE1lc3NhZ2VzICYmICFpc0Nvb2xkb3duSW5Qcm9ncmVzcyAmJiBkaXNwbGF5U2VuZEJ1dHRvbikge1xuICAgICAgICA8YnV0dG9uXG4gICAgICAgICAgZGF0YS10ZXN0aWQ9XCJzZW5kLWJ1dHRvblwiXG4gICAgICAgICAgY2xhc3M9XCJzdHItY2hhdF9fc2VuZC1idXR0b25cIlxuICAgICAgICAgIFtkaXNhYmxlZF09XCJcbiAgICAgICAgICAgIChhdHRhY2htZW50VXBsb2FkSW5Qcm9ncmVzc0NvdW50ZXIkIHwgYXN5bmMpISA+IDAgfHxcbiAgICAgICAgICAgIChhdHRhY2htZW50U2VydmljZS5hdHRhY2htZW50c0NvdW50ZXIkIHwgYXN5bmMpISA+XG4gICAgICAgICAgICAgIGF0dGFjaG1lbnRTZXJ2aWNlLm1heE51bWJlck9mQXR0YWNobWVudHMgfHxcbiAgICAgICAgICAgICghdGV4dGFyZWFWYWx1ZSAmJlxuICAgICAgICAgICAgICAoYXR0YWNobWVudFVwbG9hZHMkIHwgYXN5bmMpIS5sZW5ndGggPT09IDAgJiZcbiAgICAgICAgICAgICAgKGN1c3RvbUF0dGFjaG1lbnRzJCB8IGFzeW5jKSEubGVuZ3RoID09PSAwKVxuICAgICAgICAgIFwiXG4gICAgICAgICAgKGNsaWNrKT1cIm1lc3NhZ2VTZW50KClcIlxuICAgICAgICAgIChrZXl1cC5lbnRlcik9XCJtZXNzYWdlU2VudCgpXCJcbiAgICAgICAgPlxuICAgICAgICAgIDxzdHJlYW0taWNvbi1wbGFjZWhvbGRlciBpY29uPVwic2VuZFwiIC8+XG4gICAgICAgIDwvYnV0dG9uPlxuICAgICAgfVxuICAgICAgQGlmIChpc0Nvb2xkb3duSW5Qcm9ncmVzcykge1xuICAgICAgICA8ZGl2XG4gICAgICAgICAgY2xhc3M9XCJzdHItY2hhdF9fbWVzc2FnZS1pbnB1dC1jb29sZG93blwiXG4gICAgICAgICAgZGF0YS10ZXN0aWQ9XCJjb29sZG93bi10aW1lclwiXG4gICAgICAgID5cbiAgICAgICAgICB7eyBjb29sZG93biQgfCBhc3luYyB9fVxuICAgICAgICA8L2Rpdj5cbiAgICAgIH1cbiAgICAgIEBpZiAoZGlzcGxheVZvaWNlUmVjb3JkaW5nQnV0dG9uKSB7XG4gICAgICAgIDxidXR0b25cbiAgICAgICAgICBjbGFzcz1cInN0ci1jaGF0X19zdGFydC1yZWNvcmRpbmctYXVkaW8tYnV0dG9uXCJcbiAgICAgICAgICBkYXRhLXRlc3RpZD1cInN0YXJ0LXZvaWNlLXJlY29yZGluZ1wiXG4gICAgICAgICAgW2Rpc2FibGVkXT1cIlxuICAgICAgICAgICAgdm9pY2VSZWNvcmRlclNlcnZpY2UuaXNSZWNvcmRlclZpc2libGUkLnZhbHVlIHx8XG4gICAgICAgICAgICBhdWRpb1JlY29yZGVyPy5pc1JlY29yZGluZyB8fFxuICAgICAgICAgICAgKGF0dGFjaG1lbnRTZXJ2aWNlLmF0dGFjaG1lbnRzQ291bnRlciQgfCBhc3luYykhID49XG4gICAgICAgICAgICAgIGF0dGFjaG1lbnRTZXJ2aWNlLm1heE51bWJlck9mQXR0YWNobWVudHNcbiAgICAgICAgICBcIlxuICAgICAgICAgIChjbGljayk9XCJzdGFydFZvaWNlUmVjb3JkaW5nKClcIlxuICAgICAgICAgIChrZXl1cC5lbnRlcik9XCJzdGFydFZvaWNlUmVjb3JkaW5nKClcIlxuICAgICAgICA+XG4gICAgICAgICAgPHN0cmVhbS1pY29uLXBsYWNlaG9sZGVyIGljb249XCJtaWNcIiAvPlxuICAgICAgICA8L2J1dHRvbj5cbiAgICAgIH1cbiAgICAgIDxuZy1jb250ZW50IHNlbGVjdD1cIlttZXNzYWdlLWlucHV0LWVuZF1cIiAvPlxuICAgIDwvZGl2PlxuICB9IEBlbHNlIHtcbiAgICA8ZGl2XG4gICAgICBjbGFzcz1cInN0ci1jaGF0X19tZXNzYWdlLWlucHV0LW5vdC1hbGxvd2VkXCJcbiAgICAgIGRhdGEtdGVzdGlkPVwiZGlzYWJsZWQtdGV4dGFyZWFcIlxuICAgID5cbiAgICAgIHt7IGRpc2FibGVkVGV4dGFyZWFUZXh0IHwgdHJhbnNsYXRlIH19XG4gICAgPC9kaXY+XG4gIH1cbjwvZGl2PlxuQGlmICh2b2ljZVJlY29yZGVyUmVmKSB7XG4gIDxuZy10ZW1wbGF0ZVxuICAgIFtuZ1RlbXBsYXRlT3V0bGV0XT1cInZvaWNlUmVjb3JkZXJSZWZcIlxuICAgIFtuZ1RlbXBsYXRlT3V0bGV0Q29udGV4dF09XCJ7IHNlcnZpY2U6IHZvaWNlUmVjb3JkZXJTZXJ2aWNlIH1cIlxuICAvPlxufVxuIl19