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
@@ -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/v6-rc/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
+ ngOnInit() {
156
+ this.subscriptions.push(this.customTemplatesService.emojiPickerTemplate$.subscribe((template) => {
157
+ this.emojiPickerTemplate = template;
158
+ this.cdRef.detectChanges();
159
+ }));
160
+ this.subscriptions.push(this.customTemplatesService.attachmentPreviewListTemplate$.subscribe((template) => {
161
+ this.attachmentPreviewListTemplate = template;
162
+ this.cdRef.detectChanges();
163
+ }));
164
+ this.subscriptions.push(this.customTemplatesService.customAttachmentUploadTemplate$.subscribe((template) => {
165
+ this.customAttachmentUploadTemplate = template;
166
+ this.cdRef.detectChanges();
167
+ }));
168
+ }
169
+ ngAfterViewInit() {
170
+ this.isViewInited = true;
171
+ this.initTextarea();
172
+ }
173
+ ngOnChanges(changes) {
174
+ if (changes.message) {
175
+ this.messageToUpdateChanged();
176
+ }
177
+ if (changes.isFileUploadEnabled) {
178
+ this.configService.isFileUploadEnabled = this.isFileUploadEnabled;
179
+ }
180
+ if (changes.isMultipleFileUploadEnabled) {
181
+ this.configService.isMultipleFileUploadEnabled =
182
+ this.isMultipleFileUploadEnabled;
183
+ }
184
+ if (changes.areMentionsEnabled) {
185
+ this.configService.areMentionsEnabled = this.areMentionsEnabled;
186
+ }
187
+ if (changes.mentionScope) {
188
+ this.configService.mentionScope = this.mentionScope;
189
+ }
190
+ if (changes.mode) {
191
+ this.setCanSendMessages();
192
+ this.checkIfInEditMode();
193
+ }
194
+ if (changes.watchForMessageToEdit) {
195
+ this.checkIfInEditMode();
196
+ }
197
+ if (changes.inputMode) {
198
+ this.configService.inputMode = this.inputMode;
199
+ }
200
+ if (changes.sendMessage$) {
201
+ if (this.sendMessageSubcription) {
202
+ this.sendMessageSubcription.unsubscribe();
203
+ }
204
+ if (this.sendMessage$) {
205
+ this.sendMessageSubcription = this.sendMessage$.subscribe(() => void this.messageSent());
206
+ }
207
+ }
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
+ }
459
+ MessageInputComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.4", 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 });
460
+ MessageInputComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.0.4", 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 <div *ngIf=\"quotedMessage\" 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\"></stream-icon-placeholder>\n </button>\n </div>\n <div *ngIf=\"isUpdate\" 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\"></stream-icon-placeholder>\n </button>\n </div>\n <ng-container *ngIf=\"canSendMessages; else notAllowed\">\n <div\n class=\"str-chat__message-input-inner str-chat-angular__message-input-inner\"\n >\n <ng-content select=\"[message-input-start]\"></ng-content>\n <ng-container\n *ngIf=\"isFileUploadEnabled && isFileUploadAuthorized && canSendMessages\"\n >\n <ng-container\n *ngTemplateOutlet=\"\n customAttachmentUploadTemplate || defaultAttachmentUpload;\n context: getAttachmentUploadContext()\n \"\n ></ng-container>\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\"></stream-icon-placeholder>\n </label>\n </div>\n </ng-template>\n </ng-container>\n <div class=\"str-chat__message-textarea-container\">\n <div\n *ngIf=\"quotedMessage\"\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 ></stream-avatar-placeholder>\n <div\n class=\"quoted-message-preview-content-inner str-chat__quoted-message-bubble\"\n >\n <stream-attachment-list\n *ngIf=\"\n quotedMessage?.attachments && quotedMessage?.attachments?.length\n \"\n [attachments]=\"quotedMessageAttachments\"\n [messageId]=\"quotedMessage.id\"\n ></stream-attachment-list>\n <div class=\"str-chat__quoted-message-text\">\n <ng-container\n *ngTemplateOutlet=\"\n (customTemplatesService.messageTextTemplate$ | async) ||\n defaultText;\n context: getQuotedMessageTextContext()\n \"\n ></ng-container>\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 ></stream-message-text>\n </ng-template>\n </div>\n </div>\n </div>\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 ></stream-attachment-preview-list>\n </ng-template>\n <ng-container\n *ngTemplateOutlet=\"\n attachmentPreviewListTemplate || defaultAttachmentsPreview;\n context: getAttachmentPreviewListContext()\n \"\n ></ng-container>\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 ></ng-container>\n <ng-container *ngIf=\"emojiPickerTemplate\" data-testid=\"emoji-picker\">\n <ng-container\n *ngTemplateOutlet=\"\n emojiPickerTemplate;\n context: getEmojiPickerContext()\n \"\n ></ng-container>\n </ng-container>\n </div>\n </div>\n <button\n *ngIf=\"canSendMessages && !isCooldownInProgress && displaySendButton\"\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\"></stream-icon-placeholder>\n </button>\n <div\n *ngIf=\"isCooldownInProgress\"\n class=\"str-chat__message-input-cooldown\"\n data-testid=\"cooldown-timer\"\n >\n {{ cooldown$ | async }}\n </div>\n <button\n *ngIf=\"displayVoiceRecordingButton\"\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\"></stream-icon-placeholder>\n </button>\n <ng-content select=\"[message-input-end]\"></ng-content>\n </div>\n </ng-container>\n <ng-template #notAllowed>\n <div\n class=\"str-chat__message-input-not-allowed\"\n data-testid=\"disabled-textarea\"\n >\n {{ disabledTextareaText | translate }}\n </div>\n </ng-template>\n</div>\n<ng-template\n *ngIf=\"voiceRecorderRef\"\n [ngTemplateOutlet]=\"voiceRecorderRef\"\n [ngTemplateOutletContext]=\"{ service: voiceRecorderService }\"\n></ng-template>\n", dependencies: [{ kind: "directive", type: i10.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { 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" }] });
461
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.4", 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 <div *ngIf=\"quotedMessage\" 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\"></stream-icon-placeholder>\n </button>\n </div>\n <div *ngIf=\"isUpdate\" 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\"></stream-icon-placeholder>\n </button>\n </div>\n <ng-container *ngIf=\"canSendMessages; else notAllowed\">\n <div\n class=\"str-chat__message-input-inner str-chat-angular__message-input-inner\"\n >\n <ng-content select=\"[message-input-start]\"></ng-content>\n <ng-container\n *ngIf=\"isFileUploadEnabled && isFileUploadAuthorized && canSendMessages\"\n >\n <ng-container\n *ngTemplateOutlet=\"\n customAttachmentUploadTemplate || defaultAttachmentUpload;\n context: getAttachmentUploadContext()\n \"\n ></ng-container>\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\"></stream-icon-placeholder>\n </label>\n </div>\n </ng-template>\n </ng-container>\n <div class=\"str-chat__message-textarea-container\">\n <div\n *ngIf=\"quotedMessage\"\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 ></stream-avatar-placeholder>\n <div\n class=\"quoted-message-preview-content-inner str-chat__quoted-message-bubble\"\n >\n <stream-attachment-list\n *ngIf=\"\n quotedMessage?.attachments && quotedMessage?.attachments?.length\n \"\n [attachments]=\"quotedMessageAttachments\"\n [messageId]=\"quotedMessage.id\"\n ></stream-attachment-list>\n <div class=\"str-chat__quoted-message-text\">\n <ng-container\n *ngTemplateOutlet=\"\n (customTemplatesService.messageTextTemplate$ | async) ||\n defaultText;\n context: getQuotedMessageTextContext()\n \"\n ></ng-container>\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 ></stream-message-text>\n </ng-template>\n </div>\n </div>\n </div>\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 ></stream-attachment-preview-list>\n </ng-template>\n <ng-container\n *ngTemplateOutlet=\"\n attachmentPreviewListTemplate || defaultAttachmentsPreview;\n context: getAttachmentPreviewListContext()\n \"\n ></ng-container>\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 ></ng-container>\n <ng-container *ngIf=\"emojiPickerTemplate\" data-testid=\"emoji-picker\">\n <ng-container\n *ngTemplateOutlet=\"\n emojiPickerTemplate;\n context: getEmojiPickerContext()\n \"\n ></ng-container>\n </ng-container>\n </div>\n </div>\n <button\n *ngIf=\"canSendMessages && !isCooldownInProgress && displaySendButton\"\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\"></stream-icon-placeholder>\n </button>\n <div\n *ngIf=\"isCooldownInProgress\"\n class=\"str-chat__message-input-cooldown\"\n data-testid=\"cooldown-timer\"\n >\n {{ cooldown$ | async }}\n </div>\n <button\n *ngIf=\"displayVoiceRecordingButton\"\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\"></stream-icon-placeholder>\n </button>\n <ng-content select=\"[message-input-end]\"></ng-content>\n </div>\n </ng-container>\n <ng-template #notAllowed>\n <div\n class=\"str-chat__message-input-not-allowed\"\n data-testid=\"disabled-textarea\"\n >\n {{ disabledTextareaText | translate }}\n </div>\n </ng-template>\n</div>\n<ng-template\n *ngIf=\"voiceRecorderRef\"\n [ngTemplateOutlet]=\"voiceRecorderRef\"\n [ngTemplateOutletContext]=\"{ service: voiceRecorderService }\"\n></ng-template>\n" }]
464
+ }], ctorParameters: function () { return [{ 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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWVzc2FnZS1pbnB1dC5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9zdHJlYW0tY2hhdC1hbmd1bGFyL3NyYy9saWIvbWVzc2FnZS1pbnB1dC9tZXNzYWdlLWlucHV0LmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL3N0cmVhbS1jaGF0LWFuZ3VsYXIvc3JjL2xpYi9tZXNzYWdlLWlucHV0L21lc3NhZ2UtaW5wdXQuY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUdMLFNBQVMsRUFHVCxZQUFZLEVBRVosWUFBWSxFQUNaLFdBQVcsRUFDWCxNQUFNLEVBQ04sS0FBSyxFQUlMLFFBQVEsRUFDUixNQUFNLEVBRU4sV0FBVyxFQUVYLFNBQVMsR0FDVixNQUFNLGVBQWUsQ0FBQztBQUN2QixPQUFPLEVBQUUsYUFBYSxFQUFjLE9BQU8sRUFBZ0IsS0FBSyxFQUFFLE1BQU0sTUFBTSxDQUFDO0FBQy9FLE9BQU8sRUFBRSxLQUFLLEVBQUUsR0FBRyxFQUFFLElBQUksRUFBRSxHQUFHLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUV2RCxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSx1QkFBdUIsQ0FBQztBQUUxRCxPQUFPLEVBQUUsc0JBQXNCLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQVk3RCxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSxzQkFBc0IsQ0FBQztBQUV6RCxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSx1QkFBdUIsQ0FBQztBQUUxRCxPQUFPLEVBQUUsRUFBRSxJQUFJLE1BQU0sRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUVwQyxPQUFPLEVBQUUsb0JBQW9CLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQzs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUdoRTs7R0FFRztBQU9ILE1BQU0sT0FBTyxxQkFBcUI7SUFrR2hDLFlBQ1UsY0FB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QWEsR0FBRyxFQUFFLENBQUM7U0FDekI7SUFDSCxDQUFDOztrSEE3a0JVLHFCQUFxQiw2SkF1R3RCLHNCQUFzQjtzR0F2R3JCLHFCQUFxQiw2a0JBRnJCLENBQUMsaUJBQWlCLEVBQUUsaUJBQWlCLEVBQUUsb0JBQW9CLENBQUMsd0VBNkR6RCxXQUFXLHlMQTRCZCxpQkFBaUIscUVDaEo5QiwrM1FBeU5BOzJGRGhLYSxxQkFBcUI7a0JBTmpDLFNBQVM7K0JBQ0Usc0JBQXNCLGFBR3JCLENBQUMsaUJBQWlCLEVBQUUsaUJBQWlCLEVBQUUsb0JBQW9CLENBQUM7OzBCQXlHcEUsTUFBTTsyQkFBQyxzQkFBc0I7OzBCQVE3QixRQUFROzRDQXpHRixtQkFBbUI7c0JBQTNCLEtBQUs7Z0JBSUcsa0JBQWtCO3NCQUExQixLQUFLO2dCQUlHLFlBQVk7c0JBQXBCLEtBQUs7Z0JBSUcsSUFBSTtzQkFBWixLQUFLO2dCQUlHLDJCQUEyQjtzQkFBbkMsS0FBSztnQkFJRyxPQUFPO3NCQUFmLEtBQUs7Z0JBSUcsWUFBWTtzQkFBcEIsS0FBSztnQkFJRyxTQUFTO3NCQUFqQixLQUFLO2dCQUlHLFNBQVM7c0JBQWpCLEtBQUs7Z0JBTUcscUJBQXFCO3NCQUE3QixLQUFLO2dCQUlHLGlCQUFpQjtzQkFBekIsS0FBSztnQkFJRywyQkFBMkI7c0JBQW5DLEtBQUs7Z0JBSWEsYUFBYTtzQkFBL0IsTUFBTTtnQkFHb0IsZ0JBQWdCO3NCQUExQyxZQUFZO3VCQUFDLFdBQVc7Z0JBR1YsS0FBSztzQkFBbkIsV0FBVztnQkF3Qm9CLFNBQVM7c0JBQXhDLFNBQVM7dUJBQUMsV0FBVztnQkFFZCxjQUFjO3NCQURyQixTQUFTO3VCQUFDLGlCQUFpQixFQUFFLEVBQUUsTUFBTSxFQUFFLEtBQUssRUFBRSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XG4gIEFmdGVyVmlld0luaXQsXG4gIENoYW5nZURldGVjdG9yUmVmLFxuICBDb21wb25lbnQsXG4gIENvbXBvbmVudEZhY3RvcnlSZXNvbHZlcixcbiAgQ29tcG9uZW50UmVmLFxuICBDb250ZW50Q2hpbGQsXG4gIEVsZW1lbnRSZWYsXG4gIEV2ZW50RW1pdHRlcixcbiAgSG9zdEJpbmRpbmcsXG4gIEluamVjdCxcbiAgSW5wdXQsXG4gIE9uQ2hhbmdlcyxcbiAgT25EZXN0cm95LFxuICBPbkluaXQsXG4gIE9wdGlvbmFsLFxuICBPdXRwdXQsXG4gIFNpbXBsZUNoYW5nZXMsXG4gIFRlbXBsYXRlUmVmLFxuICBUeXBlLFxuICBWaWV3Q2hpbGQsXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgY29tYmluZUxhdGVzdCwgT2JzZXJ2YWJsZSwgU3ViamVjdCwgU3Vic2NyaXB0aW9uLCB0aW1lciB9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHsgZmlyc3QsIG1hcCwgdGFrZSwgdGFwIH0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xuaW1wb3J0IHsgQXR0YWNobWVudCwgQ2hhbm5lbCwgVXNlclJlc3BvbnNlIH0gZnJvbSAnc3RyZWFtLWNoYXQnO1xuaW1wb3J0IHsgQXR0YWNobWVudFNlcnZpY2UgfSBmcm9tICcuLi9hdHRhY2htZW50LnNlcnZpY2UnO1xuaW1wb3J0IHsgQ2hhbm5lbFNlcnZpY2UgfSBmcm9tICcuLi9jaGFubmVsLnNlcnZpY2UnO1xuaW1wb3J0IHsgdGV4dGFyZWFJbmplY3Rpb25Ub2tlbiB9IGZyb20gJy4uL2luamVjdGlvbi10b2tlbnMnO1xuaW1wb3J0IHsgTm90aWZpY2F0aW9uU2VydmljZSB9IGZyb20gJy4uL25vdGlmaWNhdGlvbi5zZXJ2aWNlJztcbmltcG9ydCB7XG4gIEF0dGFjaG1lbnRQcmV2aWV3TGlzdENvbnRleHQsXG4gIEF0dGFjaG1lbnRVcGxvYWQsXG4gIEF1ZGlvUmVjb3JkaW5nLFxuICBDdXN0b21BdHRhY2htZW50VXBsb2FkQ29udGV4dCxcbiAgRW1vamlQaWNrZXJDb250ZXh0LFxuICBNZXNzYWdlVGV4dENvbnRleHQsXG4gIFN0cmVhbU1lc3NhZ2UsXG59IGZyb20gJy4uL3R5cGVzJztcbmltcG9ydCB7IE1lc3NhZ2VJbnB1dENvbmZpZ1NlcnZpY2UgfSBmcm9tICcuL21lc3NhZ2UtaW5wdXQtY29uZmlnLnNlcnZpY2UnO1xuaW1wb3J0IHsgVGV4dGFyZWFEaXJlY3RpdmUgfSBmcm9tICcuL3RleHRhcmVhLmRpcmVjdGl2ZSc7XG5pbXBvcnQgeyBUZXh0YXJlYUludGVyZmFjZSB9IGZyb20gJy4vdGV4dGFyZWEuaW50ZXJmYWNlJztcbmltcG9ydCB7IEVtb2ppSW5wdXRTZXJ2aWNlIH0gZnJvbSAnLi9lbW9qaS1pbnB1dC5zZXJ2aWNlJztcbmltcG9ydCB7IEN1c3RvbVRlbXBsYXRlc1NlcnZpY2UgfSBmcm9tICcuLi9jdXN0b20tdGVtcGxhdGVzLnNlcnZpY2UnO1xuaW1wb3J0IHsgdjQgYXMgdXVpZHY0IH0gZnJvbSAndXVpZCc7XG5pbXBvcnQgeyBNZXNzYWdlQWN0aW9uc1NlcnZpY2UgfSBmcm9tICcuLi9tZXNzYWdlLWFjdGlvbnMuc2VydmljZSc7XG5pbXBvcnQgeyBWb2ljZVJlY29yZGVyU2VydmljZSB9IGZyb20gJy4vdm9pY2UtcmVjb3JkZXIuc2VydmljZSc7XG5pbXBvcnQgeyBBdWRpb1JlY29yZGVyU2VydmljZSB9IGZyb20gJy4uL3ZvaWNlLXJlY29yZGVyL2F1ZGlvLXJlY29yZGVyLnNlcnZpY2UnO1xuXG4vKipcbiAqIFRoZSBgTWVzc2FnZUlucHV0YCBjb21wb25lbnQgZGlzcGxheXMgYW4gaW5wdXQgd2hlcmUgdXNlcnMgY2FuIHR5cGUgdGhlaXIgbWVzc2FnZXMgYW5kIHVwbG9hZCBmaWxlcywgYW5kIHNlbmRzIHRoZSBtZXNzYWdlIHRvIHRoZSBhY3RpdmUgY2hhbm5lbC4gVGhlIGNvbXBvbmVudCBjYW4gYmUgdXNlZCB0byBjb21wb3NlIG5ldyBtZXNzYWdlcyBvciB1cGRhdGUgZXhpc3Rpbmcgb25lcy4gVG8gc2VuZCBtZXNzYWdlcywgdGhlIGNoYXQgdXNlciBuZWVkcyB0byBoYXZlIHRoZSBuZWNlc3NhcnkgW2NoYW5uZWwgY2FwYWJpbGl0eV0oL2NoYXQvZG9jcy9qYXZhc2NyaXB0L2NoYW5uZWxfY2FwYWJpbGl0aWVzLykuXG4gKi9cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ3N0cmVhbS1tZXNzYWdlLWlucHV0JyxcbiAgdGVtcGxhdGVVcmw6ICcuL21lc3NhZ2UtaW5wdXQuY29tcG9uZW50Lmh0bWwnLFxuICBzdHlsZXM6IFtdLFxuICBwcm92aWRlcnM6IFtBdHRhY2htZW50U2VydmljZSwgRW1vamlJbnB1dFNlcnZpY2UsIFZvaWNlUmVjb3JkZXJTZXJ2aWNlXSxcbn0pXG5leHBvcnQgY2xhc3MgTWVzc2FnZUlucHV0Q29tcG9uZW50XG4gIGltcGxlbWVudHMgT25Jbml0LCBPbkNoYW5nZXMsIE9uRGVzdHJveSwgQWZ0ZXJWaWV3SW5pdFxue1xuICAvKipcbiAgICogSWYgZmlsZSB1cGxvYWQgaXMgZW5hYmxlZCwgdGhlIHVzZXIgY2FuIG9wZW4gYSBmaWxlIHNlbGVjdG9yIGZyb20gdGhlIGlucHV0LiBQbGVhc2Ugbm90ZSB0aGF0IHRoZSB1c2VyIGFsc28gbmVlZHMgdG8gaGF2ZSB0aGUgbmVjZXNzYXJ5IFtjaGFubmVsIGNhcGFiaWxpdHldKC9jaGF0L2RvY3MvamF2YXNjcmlwdC9jaGFubmVsX2NhcGFiaWxpdGllcy8pLiBJZiBubyB2YWx1ZSBpcyBwcm92aWRlZCwgaXQgaXMgc2V0IGZyb20gdGhlIFtgTWVzc2FnZUlucHV0Q29uZmlnU2VydmljZWBdKC9jaGF0L2RvY3Mvc2RrL2FuZ3VsYXIvdjYtcmMvc2VydmljZXMvTWVzc2FnZUlucHV0Q29uZmlnU2VydmljZS8pLlxuICAgKi9cbiAgQElucHV0KCkgaXNGaWxlVXBsb2FkRW5hYmxlZDogYm9vbGVhbiB8IHVuZGVmaW5lZDtcbiAgLyoqXG4gICAqIElmIHRydWUsIHVzZXJzIGNhbiBtZW50aW9uIG90aGVyIHVzZXJzIGluIG1lc3NhZ2VzLiBZb3UgYWxzbyBbbmVlZCB0byB1c2UgdGhlIGBBdXRvY29tcGxldGVUZXh0YXJlYWBdKC9jaGF0L2RvY3Mvc2RrL2FuZ3VsYXIvdjYtcmMvY29uY2VwdHMvb3B0LWluLWFyY2hpdGVjdHVyZS8pIGZvciB0aGlzIGZlYXR1cmUgdG8gd29yay4gSWYgbm8gdmFsdWUgaXMgcHJvdmlkZWQsIGl0IGlzIHNldCBmcm9tIHRoZSBbYE1lc3NhZ2VJbnB1dENvbmZpZ1NlcnZpY2VgXSgvY2hhdC9kb2NzL3Nkay9hbmd1bGFyL3Y2LXJjL3NlcnZpY2VzL01lc3NhZ2VJbnB1dENvbmZpZ1NlcnZpY2UvKS5cbiAgICovXG4gIEBJbnB1dCgpIGFyZU1lbnRpb25zRW5hYmxlZDogYm9vbGVhbiB8IHVuZGVmaW5lZDtcbiAgLyoqXG4gICAqIFRoZSBzY29wZSBmb3IgdXNlciBtZW50aW9ucywgZWl0aGVyIG1lbWJlcnMgb2YgdGhlIGN1cnJlbnQgY2hhbm5lbCBvZiBtZW1iZXJzIG9mIHRoZSBhcHBsaWNhdGlvbi4gSWYgbm8gdmFsdWUgaXMgcHJvdmlkZWQsIGl0IGlzIHNldCBmcm9tIHRoZSBbYE1lc3NhZ2VJbnB1dENvbmZpZ1NlcnZpY2VgXSgvY2hhdC9kb2NzL3Nkay9hbmd1bGFyL3Y2LXJjL3NlcnZpY2VzL01lc3NhZ2VJbnB1dENvbmZpZ1NlcnZpY2UvKS5cbiAgICovXG4gIEBJbnB1dCgpIG1lbnRpb25TY29wZTogJ2NoYW5uZWwnIHwgJ2FwcGxpY2F0aW9uJyB8IHVuZGVmaW5lZDtcbiAgLyoqXG4gICAqIERldGVybWluZXMgaWYgdGhlIG1lc3NhZ2UgaXMgYmVpbmcgZGlzcGFseWVkIGluIGEgY2hhbm5lbCBvciBpbiBhIFt0aHJlYWRdKC9jaGF0L2RvY3MvamF2YXNjcmlwdC90aHJlYWRzLykuXG4gICAqL1xuICBASW5wdXQoKSBtb2RlOiAndGhyZWFkJyB8ICdtYWluJyA9ICdtYWluJztcbiAgLyoqXG4gICAqIElmIHRydWUsIHVzZXJzIGNhbiBzZWxlY3QgbXVsdGlwbGUgZmlsZXMgdG8gdXBsb2FkLiBJZiBubyB2YWx1ZSBpcyBwcm92aWRlZCwgaXQgaXMgc2V0IGZyb20gdGhlIFtgTWVzc2FnZUlucHV0Q29uZmlnU2VydmljZWBdKC9jaGF0L2RvY3Mvc2RrL2FuZ3VsYXIvdjYtcmMvc2VydmljZXMvTWVzc2FnZUlucHV0Q29uZmlnU2VydmljZS8pLlxuICAgKi9cbiAgQElucHV0KCkgaXNNdWx0aXBsZUZpbGVVcGxvYWRFbmFibGVkOiBib29sZWFuIHwgdW5kZWZpbmVkO1xuICAvKipcbiAgICogVGhlIG1lc3NhZ2UgdG8gZWRpdFxuICAgKi9cbiAgQElucHV0KCkgbWVzc2FnZTogU3RyZWFtTWVzc2FnZSB8IHVuZGVmaW5lZDtcbiAgLyoqXG4gICAqIEFuIG9ic2VydmFibGUgdGhhdCBjYW4gYmUgdXNlZCB0byB0cmlnZ2VyIG1lc3NhZ2Ugc2VuZGluZyBmcm9tIHRoZSBvdXRzaWRlXG4gICAqL1xuICBASW5wdXQoKSBzZW5kTWVzc2FnZSQ6IE9ic2VydmFibGU8dm9pZD4gfCB1bmRlZmluZWQ7XG4gIC8qKlxuICAgKiBJbiBgZGVza3RvcGAgbW9kZSB0aGUgYEVudGVyYCBrZXkgd2lsbCB0cmlnZ2VyIG1lc3NhZ2Ugc2VuZGluZywgaW4gYG1vYmlsZWAgbW9kZSB0aGUgYEVudGVyYCBrZXkgd2lsbCBpbnNlcnQgYSBuZXcgbGluZSB0byB0aGUgbWVzc2FnZSBpbnB1dC4gSWYgbm8gdmFsdWUgaXMgcHJvdmlkZWQsIGl0IGlzIHNldCBmcm9tIHRoZSBbYE1lc3NhZ2VJbnB1dENvbmZpZ1NlcnZpY2VgXSgvY2hhdC9kb2NzL3Nkay9hbmd1bGFyL3Y2LXJjL3NlcnZpY2VzL01lc3NhZ2VJbnB1dENvbmZpZ1NlcnZpY2UvKS5cbiAgICovXG4gIEBJbnB1dCgpIGlucHV0TW9kZTogJ2Rlc2t0b3AnIHwgJ21vYmlsZSc7XG4gIC8qKlxuICAgKiBFbmFibGVzIG9yIGRpc2FibGVzIGF1dG8gZm9jdXMgb24gdGhlIHRleHRhcmVhIGVsZW1lbnRcbiAgICovXG4gIEBJbnB1dCgpIGF1dG9Gb2N1cyA9IHRydWU7XG4gIC8qKlxuICAgKiBCeSBkZWZhdWx0IHRoZSBpbnB1dCB3aWxsIHJlYWN0IHRvIGNoYW5nZXMgaW4gYG1lc3NhZ2VUb0VkaXQkYCBmcm9tIFtgTWVzc2FnZUFjdGlvbnNTZXJ2aWNlYF0oL2NoYXQvZG9jcy9zZGsvYW5ndWxhci92Ni1yYy9zZXJ2aWNlcy9NZXNzYWdlQWN0aW9uc1NlcnZpY2UvKSBhbmQgZGlzcGxheSB0aGUgbWVzc2FnZSB0byBiZSBlZGl0ZWQgKHRha2luZyBpbnRvIGFjY291bnQgdGhlIGN1cnJlbnQgYG1vZGVgKS5cbiAgICpcbiAgICogSWYgeW91IGRvbid0IG5lZWQgdGhhdCBiZWhhdmlvciwgeW91IGNhbiB0dXJuIHRoaXMgb2Ygd2l0aCB0aGlzIGZsYWcuIEluIHRoYXQgY2FzZSB5b3Ugc2hvdWxkIGNyZWF0ZSB5b3VyIG93biBlZGl0IG1lc3NhZ2UgVUkuXG4gICAqL1xuICBASW5wdXQoKSB3YXRjaEZvck1lc3NhZ2VUb0VkaXQgPSB0cnVlO1xuICAvKipcbiAgICogVXNlIHRoaXMgaW5wdXQgdG8gY29udHJvbCB3ZXRoZXIgYSBzZW5kIGJ1dHRvbiBpcyByZW5kZXJlZCBvciBub3QuIElmIHlvdSBkb24ndCByZW5kZXIgYSBzZW5kIGJ1dHRvbiwgeW91IGNhbiBzdGlsbCB0cmlnZ2VyIG1lc3NhZ2Ugc2VuZCB1c2luZyB0aGUgYHNlbmRNZXNzYWdlJGAgaW5wdXQuXG4gICAqL1xuICBASW5wdXQoKSBkaXNwbGF5U2VuZEJ1dHRvbiA9IHRydWU7XG4gIC8qKlxuICAgKiBZb3UgY2FuIGVuYWJsZS9kaXNhYmxlIHZvaWNlIHJlY29yZGluZ3Mgd2l0aCB0aGlzIGlucHV0XG4gICAqL1xuICBASW5wdXQoKSBkaXNwbGF5Vm9pY2VSZWNvcmRpbmdCdXR0b24gPSBmYWxzZTtcbiAgLyoqXG4gICAqIEVtaXRzIHdoZW4gYSBtZXNzYWdlIHdhcyBzdWNjZXNzZnVseSBzZW50IG9yIHVwZGF0ZWRcbiAgICovXG4gIEBPdXRwdXQoKSByZWFkb25seSBtZXNzYWdlVXBkYXRlID0gbmV3IEV2ZW50RW1pdHRlcjx7XG4gICAgbWVzc2FnZTogU3RyZWFtTWVzc2FnZTtcbiAgfT4oKTtcbiAgQENvbnRlbnRDaGlsZChUZW1wbGF0ZVJlZikgdm9pY2VSZWNvcmRlclJlZjpcbiAgICB8IFRlbXBsYXRlUmVmPHsgc2VydmljZTogVm9pY2VSZWNvcmRlclNlcnZpY2UgfT5cbiAgICB8IHVuZGVmaW5lZDtcbiAgQEhvc3RCaW5kaW5nKCkgY2xhc3MgPSAnc3RyLWNoYXRfX21lc3NhZ2UtaW5wdXQtYW5ndWxhci1ob3N0JztcbiAgaXNWb2ljZVJlY29yZGluZyA9IHRydWU7XG4gIGlzRmlsZVVwbG9hZEF1dGhvcml6ZWQ6IGJvb2xlYW4gfCB1bmRlZmluZWQ7XG4gIGNhblNlbmRMaW5rczogYm9vbGVhbiB8IHVuZGVmaW5lZDtcbiAgY2FuU2VuZE1lc3NhZ2VzOiBib29sZWFuIHwgdW5kZWZpbmVkO1xuICBhdHRhY2htZW50VXBsb2FkcyQ6IE9ic2VydmFibGU8QXR0YWNobWVudFVwbG9hZFtdPjtcbiAgY3VzdG9tQXR0YWNobWVudHMkOiBPYnNlcnZhYmxlPEF0dGFjaG1lbnRbXT47XG4gIGF0dGFjaG1lbnRVcGxvYWRJblByb2dyZXNzQ291bnRlciQ6IE9ic2VydmFibGU8bnVtYmVyPjtcbiAgdGV4dGFyZWFWYWx1ZSA9ICcnO1xuICB0ZXh0YXJlYVJlZjogQ29tcG9uZW50UmVmPFRleHRhcmVhSW50ZXJmYWNlICYgUGFydGlhbDxPbkNoYW5nZXM+PiB8IHVuZGVmaW5lZDtcbiAgbWVudGlvbmVkVXNlcnM6IFVzZXJSZXNwb25zZVtdID0gW107XG4gIHF1b3RlZE1lc3NhZ2U6IHVuZGVmaW5lZCB8IFN0cmVhbU1lc3NhZ2U7XG4gIHR5cGluZ1N0YXJ0JCA9IG5ldyBTdWJqZWN0PHZvaWQ+KCk7XG4gIGNvb2xkb3duJDogT2JzZXJ2YWJsZTxudW1iZXI+IHwgdW5kZWZpbmVkO1xuICBpc0Nvb2xkb3duSW5Qcm9ncmVzcyA9IGZhbHNlO1xuICBlbW9qaVBpY2tlclRlbXBsYXRlOiBUZW1wbGF0ZVJlZjxFbW9qaVBpY2tlckNvbnRleHQ+IHwgdW5kZWZpbmVkO1xuICBjdXN0b21BdHRhY2htZW50VXBsb2FkVGVtcGxhdGU6XG4gICAgfCBUZW1wbGF0ZVJlZjxDdXN0b21BdHRhY2htZW50VXBsb2FkQ29udGV4dD5cbiAgICB8IHVuZGVmaW5lZDtcbiAgYXR0YWNobWVudFByZXZpZXdMaXN0VGVtcGxhdGU6XG4gICAgfCBUZW1wbGF0ZVJlZjxBdHRhY2htZW50UHJldmlld0xpc3RDb250ZXh0PlxuICAgIHwgdW5kZWZpbmVkO1xuICB0ZXh0YXJlYVBsYWNlaG9sZGVyOiBzdHJpbmc7XG4gIGZpbGVJbnB1dElkID0gdXVpZHY0KCk7XG4gIEBWaWV3Q2hpbGQoJ2ZpbGVJbnB1dCcpIHByaXZhdGUgZmlsZUlucHV0ITogRWxlbWVudFJlZjxIVE1MSW5wdXRFbGVtZW50PjtcbiAgQFZpZXdDaGlsZChUZXh0YXJlYURpcmVjdGl2ZSwgeyBzdGF0aWM6IGZhbHNlIH0pXG4gIHByaXZhdGUgdGV4dGFyZWFBbmNob3IhOiBUZXh0YXJlYURpcmVjdGl2ZTtcbiAgcHJpdmF0ZSBzdWJzY3JpcHRpb25zOiBTdWJzY3JpcHRpb25bXSA9IFtdO1xuICBwcml2YXRlIGhpZGVOb3RpZmljYXRpb246ICgoKSA9PiB2b2lkKSB8IHVuZGVmaW5lZDtcbiAgcHJpdmF0ZSBpc1ZpZXdJbml0ZWQgPSBmYWxzZTtcbiAgcHJpdmF0ZSBjaGFubmVsOiBDaGFubmVsIHwgdW5kZWZpbmVkO1xuICBwcml2YXRlIHNlbmRNZXNzYWdlU3ViY3JpcHRpb246IFN1YnNjcmlwdGlvbiB8IHVuZGVmaW5lZDtcbiAgcHJpdmF0ZSByZWFkb25seSBkZWZhdWx0VGV4dGFyZWFQbGFjZWhvbGRlciA9ICdzdHJlYW1DaGF0LlR5cGUgeW91ciBtZXNzYWdlJztcbiAgcHJpdmF0ZSByZWFkb25seSBzbG93TW9kZVRleHRhcmVhUGxhY2Vob2xkZXIgPSAnc3RyZWFtQ2hhdC5TbG93IE1vZGUgT04nO1xuICBwcml2YXRlIG1lc3NhZ2VUb0VkaXQ/OiBTdHJlYW1NZXNzYWdlO1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHByaXZhdGUgY2hhbm5lbFNlcnZpY2U6IENoYW5uZWxTZXJ2aWNlLFxuICAgIHByaXZhdGUgbm90aWZpY2F0aW9uU2VydmljZTogTm90aWZpY2F0aW9uU2VydmljZSxcbiAgICBwdWJsaWMgcmVhZG9ubHkgYXR0YWNobWVudFNlcnZpY2U6IEF0dGFjaG1lbnRTZXJ2aWNlLFxuICAgIHByaXZhdGUgY29uZmlnU2VydmljZTogTWVzc2FnZUlucHV0Q29uZmlnU2VydmljZSxcbiAgICBASW5qZWN0KHRleHRhcmVhSW5qZWN0aW9uVG9rZW4pXG4gICAgcHJpdmF0ZSB0ZXh0YXJlYVR5cGU6IFR5cGU8VGV4dGFyZWFJbnRlcmZhY2U+LFxuICAgIHByaXZhdGUgY29tcG9uZW50RmFjdG9yeVJlc29sdmVyOiBDb21wb25lbnRGYWN0b3J5UmVzb2x2ZXIsXG4gICAgcHJpdmF0ZSBjZFJlZjogQ2hhbmdlRGV0ZWN0b3JSZWYsXG4gICAgcHJpdmF0ZSBlbW9qaUlucHV0U2VydmljZTogRW1vamlJbnB1dFNlcnZpY2UsXG4gICAgcmVhZG9ubHkgY3VzdG9tVGVtcGxhdGVzU2VydmljZTogQ3VzdG9tVGVtcGxhdGVzU2VydmljZSxcbiAgICBwcml2YXRlIG1lc3NhZ2VBY3Rpb25zU2VydmljZTogTWVzc2FnZUFjdGlvbnNTZXJ2aWNlLFxuICAgIHB1YmxpYyByZWFkb25seSB2b2ljZVJlY29yZGVyU2VydmljZTogVm9pY2VSZWNvcmRlclNlcnZpY2UsXG4gICAgQE9wdGlvbmFsKCkgcHVibGljIGF1ZGlvUmVjb3JkZXI/OiBBdWRpb1JlY29yZGVyU2VydmljZVxuICApIHtcbiAgICB0aGlzLnRleHRhcmVhUGxhY2Vob2xkZXIgPSB0aGlzLmRlZmF1bHRUZXh0YXJlYVBsYWNlaG9sZGVyO1xuICAgIHRoaXMuc3Vic2NyaXB0aW9ucy5wdXNoKFxuICAgICAgdGhpcy5hdHRhY2htZW50U2VydmljZS5hdHRhY2htZW50VXBsb2FkSW5Qcm9ncmVzc0NvdW50ZXIkLnN1YnNjcmliZShcbiAgICAgICAgKGNvdW50ZXIpID0+IHtcbiAgICAgICAgICBpZiAoY291bnRlciA9PT0gMCAmJiB0aGlzLmhpZGVOb3RpZmljYXRpb24pIHtcbiAgICAgICAgICAgIHRoaXMuaGlkZU5vdGlmaWNhdGlvbigpO1xuICAgICAgICAgICAgdGhpcy5oaWRlTm90aWZpY2F0aW9uID0gdW5kZWZpbmVkO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgKVxuICAgICk7XG4gICAgdGhpcy5zdWJzY3JpcHRpb25zLnB1c2goXG4gICAgICB0aGlzLmNoYW5uZWxTZXJ2aWNlLmFjdGl2ZUNoYW5uZWwkLnN1YnNjcmliZSgoY2hhbm5lbCkgPT4ge1xuICAgICAgICBpZiAoY2hhbm5lbCAmJiB0aGlzLmNoYW5uZWwgJiYgY2hhbm5lbC5pZCAhPT0gdGhpcy5jaGFubmVsLmlkKSB7XG4gICAgICAgICAgdGhpcy50ZXh0YXJlYVZhbHVlID0gJyc7XG4gICAgICAgICAgdGhpcy5hdHRhY2htZW50U2VydmljZS5yZXNldEF0dGFjaG1lbnRVcGxvYWRzKCk7XG4gICAgICAgICAgdGhpcy52b2ljZVJlY29yZGVyU2VydmljZS5pc1JlY29yZGVyVmlzaWJsZSQubmV4dChmYWxzZSk7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgY2FwYWJpbGl0aWVzID0gY2hhbm5lbD8uZGF0YT8ub3duX2NhcGFiaWxpdGllcyBhcyBzdHJpbmdbXTtcbiAgICAgICAgaWYgKGNhcGFiaWxpdGllcykge1xuICAgICAgICAgIHRoaXMuaXNGaWxlVXBsb2FkQXV0aG9yaXplZCA9XG4gICAgICAgICAgICBjYXBhYmlsaXRpZXMuaW5kZXhPZigndXBsb2FkLWZpbGUnKSAhPT0gLTE7XG4gICAgICAgICAgdGhpcy5jYW5TZW5kTGlua3MgPSBjYXBhYmlsaXRpZXMuaW5kZXhPZignc2VuZC1saW5rcycpICE9PSAtMTtcbiAgICAgICAgICB0aGlzLmNoYW5uZWwgPSBjaGFubmVsO1xuICAgICAgICAgIHRoaXMuc2V0Q2FuU2VuZE1lc3NhZ2VzKCk7XG4gICAgICAgIH1cbiAgICAgIH0pXG4gICAgKTtcbiAgICB0aGlzLnN1YnNjcmlwdGlvbnMucHVzaChcbiAgICAgIHRoaXMuY2hhbm5lbFNlcnZpY2UubWVzc2FnZVRvUXVvdGUkLnN1YnNjcmliZSgobSkgPT4ge1xuICAgICAgICBjb25zdCBpc1RocmVhZFJlcGx5ID0gbSAmJiBtLnBhcmVudF9pZDtcbiAgICAgICAgaWYgKFxuICAgICAgICAgICh0aGlzLm1vZGUgPT09ICd0aHJlYWQnICYmIGlzVGhyZWFkUmVwbHkpIHx8XG4gICAgICAgICAgKHRoaXMubW9kZSA9PT0gJ3RocmVhZCcgJiYgdGhpcy5xdW90ZWRNZXNzYWdlICYmICFtKSB8fFxuICAgICAgICAgICh0aGlzLm1vZGUgPT09ICdtYWluJyAmJiAhaXNUaHJlYWRSZXBseSlcbiAgICAgICAgKSB7XG4gICAgICAgICAgdGhpcy5xdW90ZWRNZXNzYWdlID0gbTtcbiAgICAgICAgfVxuICAgICAgfSlcbiAgICApO1xuICAgIHRoaXMuc3Vic2NyaXB0aW9ucy5wdXNoKFxuICAgICAgdGhpcy5tZXNzYWdlQWN0aW9uc1NlcnZpY2UubWVzc2FnZVRvRWRpdCQuc3Vic2NyaWJlKChtZXNzYWdlKSA9PiB7XG4gICAgICAgIHRoaXMubWVzc2FnZVRvRWRpdCA9IG1lc3NhZ2U7XG4gICAgICAgIHRoaXMuY2hlY2tJZkluRWRpdE1vZGUoKTtcbiAgICAgIH0pXG4gICAgKTtcbiAgICB0aGlzLmF0dGFjaG1lbnRVcGxvYWRzJCA9IHRoaXMuYXR0YWNobWVudFNlcnZpY2UuYXR0YWNobWVudFVwbG9hZHMkO1xuICAgIHRoaXMuY3VzdG9tQXR0YWNobWVudHMkID0gdGhpcy5hdHRhY2htZW50U2VydmljZS5jdXN0b21BdHRhY2htZW50cyQ7XG4gICAgdGhpcy5hdHRhY2htZW50VXBsb2FkSW5Qcm9ncmVzc0NvdW50ZXIkID1cbiAgICAgIHRoaXMuYXR0YWNobWVudFNlcnZpY2UuYXR0YWNobWVudFVwbG9hZEluUHJvZ3Jlc3NDb3VudGVyJDtcbiAgICB0aGlzLmlzRmlsZVVwbG9hZEVuYWJsZWQgPSB0aGlzLmNvbmZpZ1NlcnZpY2UuaXNGaWxlVXBsb2FkRW5hYmxlZDtcbiAgICB0aGlzLmlzTXVsdGlwbGVGaWxlVXBsb2FkRW5hYmxlZCA9XG4gICAgICB0aGlzLmNvbmZpZ1NlcnZpY2UuaXNNdWx0aXBsZUZpbGVVcGxvYWRFbmFibGVkO1xuICAgIHRoaXMuYXJlTWVudGlvbnNFbmFibGVkID0gdGhpcy5jb25maWdTZXJ2aWNlLmFyZU1lbnRpb25zRW5hYmxlZDtcbiAgICB0aGlzLm1lbnRpb25TY29wZSA9IHRoaXMuY29uZmlnU2VydmljZS5tZW50aW9uU2NvcGU7XG4gICAgdGhpcy5pbnB1dE1vZGUgPSB0aGlzLmNvbmZpZ1NlcnZpY2UuaW5wdXRNb2RlO1xuXG4gICAgdGhpcy5zdWJzY3JpcHRpb25zLnB1c2goXG4gICAgICB0aGlzLnR5cGluZ1N0YXJ0JC5zdWJzY3JpYmUoXG4gICAgICAgICgpID0+IHZvaWQgdGhpcy5jaGFubmVsU2VydmljZS50eXBpbmdTdGFydGVkKHRoaXMucGFyZW50TWVzc2FnZUlkKVxuICAgICAgKVxuICAgICk7XG4gICAgdGhpcy5zdWJzY3JpcHRpb25zLnB1c2goXG4gICAgICB0aGlzLnZvaWNlUmVjb3JkZXJTZXJ2aWNlLmlzUmVjb3JkZXJWaXNpYmxlJC5zdWJzY3JpYmUoKGlzVmlzaWJsZSkgPT4ge1xuICAgICAgICB0aGlzLmlzVm9pY2VSZWNvcmRpbmcgPSBpc1Zpc2libGU7XG4gICAgICB9KVxuICAgICk7XG5cbiAgICB0aGlzLnN1YnNjcmlwdGlvbnMucHVzaChcbiAgICAgIGNvbWJpbmVMYXRlc3QoW1xuICAgICAgICB0aGlzLmNoYW5uZWxTZXJ2aWNlLmxhdGVzdE1lc3NhZ2VEYXRlQnlVc2VyQnlDaGFubmVscyQsXG4gICAgICAgIHRoaXMuY2hhbm5lbFNlcnZpY2UuYWN0aXZlQ2hhbm5lbCQsXG4gICAgICBdKVxuICAgICAgICAucGlwZShcbiAgICAgICAgICBtYXAoXG4gICAgICAgICAgICAoW2xhdGVzdE1lc3NhZ2VzLCBjaGFubmVsXSk6IFtcbiAgICAgICAgICAgICAgRGF0ZSB8IHVuZGVmaW5lZCxcbiAgICAgICAgICAgICAgQ2hhbm5lbCB8IHVuZGVmaW5lZFxuICAgICAgICAgICAgXSA9PiBbbGF0ZXN0TWVzc2FnZXNbY2hhbm5lbD8uY2lkIHx8ICcnXSwgY2hhbm5lbCFdXG4gICAgICAgICAgKVxuICAgICAgICApXG4gICAgICAgIC5zdWJzY3JpYmUoKFtsYXRlc3RNZXNzYWdlRGF0ZSwgY2hhbm5lbF0pID0+IHtcbiAgICAgICAgICBjb25zdCBjb29sZG93biA9XG4gICAgICAgICAgICAoY2hhbm5lbD8uZGF0YT8uY29vbGRvd24gYXMgbnVtYmVyKSAmJlxuICAgICAgICAgICAgbGF0ZXN0TWVzc2FnZURhdGUgJiZcbiAgICAgICAgICAgIE1hdGgucm91bmQoXG4gICAgICAgICAgICAgIChjaGFubmVsPy5kYXRhPy5jb29sZG93biBhcyBudW1iZXIpIC1cbiAgICAgICAgICAgICAgICAobmV3IERhdGUoKS5nZXRUaW1lKCkgLSBsYXRlc3RNZXNzYWdlRGF0ZS5nZXRUaW1lKCkpIC8gMTAwMFxuICAgICAgICAgICAgKTtcbiAgICAgICAgICBpZiAoXG4gICAgICAgICAgICBjb29sZG93biAmJlxuICAgICAgICAgICAgY29vbGRvd24gPiAwICYmXG4gICAgICAgICAgICAoY2hhbm5lbD8uZGF0YT8ub3duX2NhcGFiaWxpdGllcyBhcyBzdHJpbmdbXSkuaW5jbHVkZXMoJ3Nsb3ctbW9kZScpXG4gICAgICAgICAgKSB7XG4gICAgICAgICAgICB0aGlzLnN0YXJ0Q29vbGRvd24oY29vbGRvd24pO1xuICAgICAgICAgIH0gZWxzZSBpZiAodGhpcy5pc0Nvb2xkb3duSW5Qcm9ncmVzcykge1xuICAgICAgICAgICAgdGhpcy5zdG9wQ29vbGRvd24oKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pXG4gICAgKTtcbiAgICB0aGlzLnN1YnNjcmlwdGlvbnMucHVzaChcbiAgICAgIHRoaXMudm9pY2VSZWNvcmRlclNlcnZpY2UucmVjb3JkaW5nJC5zdWJzY3JpYmUoKHJlY29yZGluZykgPT4ge1xuICAgICAgICBpZiAocmVjb3JkaW5nKSB7XG4gICAgICAgICAgdm9pZCB0aGlzLnZvaWNlUmVjb3JkaW5nUmVhZHkocmVjb3JkaW5nKTtcbiAgICAgICAgfVxuICAgICAgfSlcbiAgICApO1xuICB9XG5cbiAgbmdPbkluaXQoKTogdm9pZCB7XG4gICAgdGhpcy5zdWJzY3JpcHRpb25zLnB1c2goXG4gICAgICB0aGlzLmN1c3RvbVRlbXBsYXRlc1NlcnZpY2UuZW1vamlQaWNrZXJUZW1wbGF0ZSQuc3Vic2NyaWJlKCh0ZW1wbGF0ZSkgPT4ge1xuICAgICAgICB0aGlzLmVtb2ppUGlja2VyVGVtcGxhdGUgPSB0ZW1wbGF0ZTtcbiAgICAgICAgdGhpcy5jZFJlZi5kZXRlY3RDaGFuZ2VzKCk7XG4gICAgICB9KVxuICAgICk7XG4gICAgdGhpcy5zdWJzY3JpcHRpb25zLnB1c2goXG4gICAgICB0aGlzLmN1c3RvbVRlbXBsYXRlc1NlcnZpY2UuYXR0YWNobWVudFByZXZpZXdMaXN0VGVtcGxhdGUkLnN1YnNjcmliZShcbiAgICAgICAgKHRlbXBsYXRlKSA9PiB7XG4gICAgICAgICAgdGhpcy5hdHRhY2htZW50UHJldmlld0xpc3RUZW1wbGF0ZSA9IHRlbXBsYXRlO1xuICAgICAgICAgIHRoaXMuY2RSZWYuZGV0ZWN0Q2hhbmdlcygpO1xuICAgICAgICB9XG4gICAgICApXG4gICAgKTtcbiAgICB0aGlzLnN1YnNjcmlwdGlvbnMucHVzaChcbiAgICAgIHRoaXMuY3VzdG9tVGVtcGxhdGVzU2VydmljZS5jdXN0b21BdHRhY2htZW50VXBsb2FkVGVtcGxhdGUkLnN1YnNjcmliZShcbiAgICAgICAgKHRlbXBsYXRlKSA9PiB7XG4gICAgICAgICAgdGhpcy5jdXN0b21BdHRhY2htZW50VXBsb2FkVGVtcGxhdGUgPSB0ZW1wbGF0ZTtcbiAgICAgICAgICB0aGlzLmNkUmVmLmRldGVjdENoYW5nZXMoKTtcbiAgICAgICAgfVxuICAgICAgKVxuICAgICk7XG4gIH1cblxuICBuZ0FmdGVyVmlld0luaXQoKTogdm9pZCB7XG4gICAgdGhpcy5pc1ZpZXdJbml0ZWQgPSB0cnVlO1xuICAgIHRoaXMuaW5pdFRleHRhcmVhKCk7XG4gIH1cblxuICBuZ09uQ2hhbmdlcyhjaGFuZ2VzOiBTaW1wbGVDaGFuZ2VzKTogdm9pZCB7XG4gICAgaWYgKGNoYW5nZXMubWVzc2FnZSkge1xuICAgICAgdGhpcy5tZXNzYWdlVG9VcGRhdGVDaGFuZ2VkKCk7XG4gICAgfVxuICAgIGlmIChjaGFuZ2VzLmlzRmlsZVVwbG9hZEVuYWJsZWQpIHtcbiAgICAgIHRoaXMuY29uZmlnU2VydmljZS5pc0ZpbGVVcGxvYWRFbmFibGVkID0gdGhpcy5pc0ZpbGVVcGxvYWRFbmFibGVkO1xuICAgIH1cbiAgICBpZiAoY2hhbmdlcy5pc011bHRpcGxlRmlsZVVwbG9hZEVuYWJsZWQpIHtcbiAgICAgIHRoaXMuY29uZmlnU2VydmljZS5pc011bHRpcGxlRmlsZVVwbG9hZEVuYWJsZWQgPVxuICAgICAgICB0aGlzLmlzTXVsdGlwbGVGaWxlVXBsb2FkRW5hYmxlZDtcbiAgICB9XG4gICAgaWYgKGNoYW5nZXMuYXJlTWVudGlvbnNFbmFibGVkKSB7XG4gICAgICB0aGlzLmNvbmZpZ1NlcnZpY2UuYXJlTWVudGlvbnNFbmFibGVkID0gdGhpcy5hcmVNZW50aW9uc0VuYWJsZWQ7XG4gICAgfVxuICAgIGlmIChjaGFuZ2VzLm1lbnRpb25TY29wZSkge1xuICAgICAgdGhpcy5jb25maWdTZXJ2aWNlLm1lbnRpb25TY29wZSA9IHRoaXMubWVudGlvblNjb3BlO1xuICAgIH1cbiAgICBpZiAoY2hhbmdlcy5tb2RlKSB7XG4gICAgICB0aGlzLnNldENhblNlbmRNZXNzYWdlcygpO1xuICAgICAgdGhpcy5jaGVja0lmSW5FZGl0TW9kZSgpO1xuICAgIH1cbiAgICBpZiAoY2hhbmdlcy53YXRjaEZvck1lc3NhZ2VUb0VkaXQpIHtcbiAgICAgIHRoaXMuY2hlY2tJZkluRWRpdE1vZGUoKTtcbiAgICB9XG4gICAgaWYgKGNoYW5nZXMuaW5wdXRNb2RlKSB7XG4gICAgICB0aGlzLmNvbmZpZ1NlcnZpY2UuaW5wdXRNb2RlID0gdGhpcy5pbnB1dE1vZGU7XG4gICAgfVxuICAgIGlmIChjaGFuZ2VzLnNlbmRNZXNzYWdlJCkge1xuICAgICAgaWYgKHRoaXMuc2VuZE1lc3NhZ2VTdWJjcmlwdGlvbikge1xuICAgICAgICB0aGlzLnNlbmRNZXNzYWdlU3ViY3JpcHRpb24udW5zdWJzY3JpYmUoKTtcbiAgICAgIH1cbiAgICAgIGlmICh0aGlzLnNlbmRNZXNzYWdlJCkge1xuICAgICAgICB0aGlzLnNlbmRNZXNzYWdlU3ViY3JpcHRpb24gPSB0aGlzLnNlbmRNZXNzYWdlJC5zdWJzY3JpYmUoXG4gICAgICAgICAgKCkgPT4gdm9pZCB0aGlzLm1lc3NhZ2VTZW50KClcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBuZ09uRGVzdHJveSgpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5zZW5kTWVzc2FnZVN1YmNyaXB0aW9uKSB7XG4gICAgICB0aGlzLnNlbmRNZXNzYWdlU3ViY3JpcHRpb24udW5zdWJzY3JpYmUoKTtcbiAgICB9XG4gICAgdGhpcy5zdWJzY3JpcHRpb25zLmZvckVhY2goKHMpID0+IHMudW5zdWJzY3JpYmUoKSk7XG4gIH1cblxuICBhc3luYyBtZXNzYWdlU2VudCgpIHtcbiAgICBpZiAodGhpcy5pc0Nvb2xkb3duSW5Qcm9ncmVzcykge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBsZXQgYXR0YWNobWVudFVwbG9hZEluUHJvZ3Jlc3NDb3VudGVyITogbnVtYmVyO1xuICAgIHRoaXMuYXR0YWNobWVudFNlcnZpY2UuYXR0YWNobWVudFVwbG9hZEluUHJvZ3Jlc3NDb3VudGVyJFxuICAgICAgLnBpcGUoZmlyc3QoKSlcbiAgICAgIC5zdWJzY3JpYmUoKGNvdW50ZXIpID0+IChhdHRhY2htZW50VXBsb2FkSW5Qcm9ncmVzc0NvdW50ZXIgPSBjb3VudGVyKSk7XG4gICAgaWYgKGF0dGFjaG1lbnRVcGxvYWRJblByb2dyZXNzQ291bnRlciA+IDApIHtcbiAgICAgIGlmICghdGhpcy5oaWRlTm90aWZpY2F0aW9uKSB7XG4gICAgICAgIHRoaXMuaGlkZU5vdGlmaWNhdGlvbiA9XG4gICAgICAgICAgdGhpcy5ub3RpZmljYXRpb25TZXJ2aWNlLmFkZFBlcm1hbmVudE5vdGlmaWNhdGlvbihcbiAgICAgICAgICAgICdzdHJlYW1DaGF0LldhaXQgdW50aWwgYWxsIGF0dGFjaG1lbnRzIGhhdmUgdXBsb2FkZWQnXG4gICAgICAgICAgKTtcbiAgICAgIH1cbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgY29uc3QgYXR0YWNobWVudHMgPSB0aGlzLmF0dGFjaG1lbnRTZXJ2aWNlLm1hcFRvQXR0YWNobWVudHMoKTtcbiAgICBsZXQgdGV4dCA9IHRoaXMudGV4dGFyZWFWYWx1ZTtcbiAgICB0ZXh0ID0gdGV4dC5yZXBsYWNlKC9eXFxuKy9nLCAnJyk7IC8vIGxlYWRpbmcgZW1wdHkgbGluZXNcbiAgICB0ZXh0ID0gdGV4dC5yZXBsYWNlKC9cXG4rJC9nLCAnJyk7IC8vIGVuZGluZyBlbXB0eSBsaW5lc1xuICAgIGNvbnN0IHRleHRDb250YWluc09ubHlTcGFjZUNoYXJzID0gIXRleHQucmVwbGFjZSgvIC9nLCAnJyk7IC8vc3BjYWVcbiAgICBpZiAoXG4gICAgICAoIXRleHQgfHwgdGV4dENvbnRhaW5zT25seVNwYWNlQ2hhcnMpICYmXG4gICAgICAoIWF0dGFjaG1lbnRzIHx8IGF0dGFjaG1lbnRzLmxlbmd0aCA9PT0gMClcbiAgICApIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgaWYgKHRleHRDb250YWluc09ubHlTcGFjZUNoYXJzKSB7XG4gICAgICB0ZXh0ID0gJyc7XG4gICAgfVxuICAgIGlmICh0aGlzLmNvbnRhaW5zTGlua3MgJiYgIXRoaXMuY2FuU2VuZExpbmtzKSB7XG4gICAgICB0aGlzLm5vdGlmaWNhdGlvblNlcnZpY2UuYWRkVGVtcG9yYXJ5Tm90aWZpY2F0aW9uKFxuICAgICAgICAnc3RyZWFtQ2hhdC5TZW5kaW5nIGxpbmtzIGlzIG5vdCBhbGxvd2VkIGluIHRoaXMgY29udmVyc2F0aW9uJ1xuICAgICAgKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgaWYgKCF0aGlzLmlzVXBkYXRlKSB7XG4gICAgICB0aGlzLnRleHRhcmVhVmFsdWUgPSAnJztcbiAgICB9XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IG1lc3NhZ2UgPSBhd2FpdCAodGhpcy5pc1VwZGF0ZVxuICAgICAgICA/IHRoaXMuY2hhbm5lbFNlcnZpY2UudXBkYXRlTWVzc2FnZSh7XG4gICAgICAgICAgICAuLi50aGlzLm1lc3NhZ2UhLFxuICAgICAgICAgICAgdGV4dDogdGV4dCxcbiAgICAgICAgICAgIGF0dGFjaG1lbnRzOiBhdHRhY2htZW50cyxcbiAgICAgICAgICB9KVxuICAgICAgICA6IHRoaXMuY2hhbm5lbFNlcnZpY2Uuc2VuZE1lc3NhZ2UoXG4gICAgICAgICAgICB0ZXh0LFxuICAgICAgICAgICAgYXR0YWNobWVudHMsXG4gICAgICAgICAgICB0aGlzLm1lbnRpb25lZFVzZXJzLFxuICAgICAgICAgICAgdGhpcy5wYXJlbnRNZXNzYWdlSWQsXG4gICAgICAgICAgICB0aGlzLnF1b3RlZE1lc3NhZ2U/LmlkXG4gICAgICAgICAgKSk7XG4gICAgICB0aGlzLm1lc3NhZ2VVcGRhdGUuZW1pdCh7IG1lc3NhZ2UgfSk7XG4gICAgICBpZiAodGhpcy5pc1VwZGF0ZSkge1xuICAgICAgICB0aGlzLmRlc2VsZWN0TWVzc2FnZVRvRWRpdCgpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhpcy5hdHRhY2htZW50U2VydmljZS5yZXNldEF0dGFjaG1lbnRVcGxvYWRzKCk7XG4gICAgICB9XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIGlmICh0aGlzLmlzVXBkYXRlKSB7XG4gICAgICAgIHRoaXMubm90aWZpY2F0aW9uU2VydmljZS5hZGRUZW1wb3JhcnlOb3RpZmljYXRpb24oXG4gICAgICAgICAgJ3N0cmVhbUNoYXQuRWRpdCBtZXNzYWdlIHJlcXVlc3QgZmFpbGVkJ1xuICAgICAgICApO1xuICAgICAgfVxuICAgIH1cbiAgICB2b2lkIHRoaXMuY2hhbm5lbFNlcnZpY2UudHlwaW5nU3RvcHBlZCh0aGlzLnBhcmVudE1lc3NhZ2VJZCk7XG4gICAgaWYgKHRoaXMucXVvdGVkTWVzc2FnZSkge1xuICAgICAgdGhpcy5kZXNlbGVjdE1lc3NhZ2VUb1F1b3RlKCk7XG4gICAgfVxuICB9XG5cbiAgZ2V0IGNvbnRhaW5zTGlua3MoKSB7XG4gICAgcmV0dXJuIC8oPzooPzpodHRwcz98ZnRwKTpcXC9cXC8pP1tcXHcvXFwtPz0lLl0rXFwuW1xcdy9cXC0mPz0lLl0rLy50ZXN0KFxuICAgICAgdGhpcy50ZXh0YXJlYVZhbHVlXG4gICAgKTtcbiAgfVxuXG4gIGdldCBxdW90ZWRNZXNzYWdlQXR0YWNobWVudHMoKSB7XG4gICAgY29uc3Qgb3JpZ2luYWxBdHRhY2htZW50cyA9IHRoaXMucXVvdGVkTWVzc2FnZT8uYXR0YWNobWVudHM7XG4gICAgcmV0dXJuIG9yaWdpbmFsQXR0YWNobWVudHMgJiYgb3JpZ2luYWxBdHRhY2htZW50cy5sZW5ndGhcbiAgICAgID8gW29yaWdpbmFsQXR0YWNobWVudHNbMF1dXG4gICAgICA6IFtdO1xuICB9XG5cbiAgZ2V0IGRpc2FibGVkVGV4dGFyZWFUZXh0KCkge1xuICAgIGlmICghdGhpcy5jYW5TZW5kTWVzc2FnZXMpIHtcbiAgICAgIHJldHVybiB0aGlzLm1vZGUgPT09ICd0aHJlYWQnXG4gICAgICAgID8gXCJzdHJlYW1DaGF0LllvdSBjYW4ndCBzZW5kIHRocmVhZCByZXBsaWVzIGluIHRoaXMgY2hhbm5lbFwiXG4gICAgICAgIDogXCJzdHJlYW1DaGF0LllvdSBjYW4ndCBzZW5kIG1lc3NhZ2VzIGluIHRoaXMgY2hhbm5lbFwiO1xuICAgIH1cbiAgICByZXR1cm4gJyc7XG4gIH1cblxuICBpdGVtc1Bhc3RlZChldmVudDogQ2xpcGJvYXJkRXZlbnQpIHtcbiAgICBpZiAodGhpcy5jb25maWdTZXJ2aWNlLmN1c3RvbVBhc3RlRXZlbnRIYW5kbGVyKSB7XG4gICAgICB0aGlzLmNvbmZpZ1NlcnZpY2UuY3VzdG9tUGFzdGVFdmVudEhhbmRsZXIoZXZlbnQsIHRoaXMpO1xuICAgIH0gZWxzZSB7XG4gICAgICBpZiAoZXZlbnQuY2xpcGJvYXJkRGF0YT8uZmlsZXMgJiYgZXZlbnQuY2xpcGJvYXJkRGF0YT8uZmlsZXMubGVuZ3RoID4gMCkge1xuICAgICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICB2b2lkIHRoaXMuZmlsZXNTZWxlY3RlZChldmVudC5jbGlwYm9hcmREYXRhPy5maWxlcyk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgYXN5bmMgZmlsZXNTZWxlY3RlZChmaWxlTGlzdDogRmlsZUxpc3QgfCBudWxsKSB7XG4gICAgYXdhaXQgdGhpcy5hdHRhY2htZW50U2VydmljZS5maWxlc1NlbGVjdGVkKGZpbGVMaXN0KTtcbiAgICB0aGlzLmNsZWFyRmlsZUlucHV0KCk7XG4gIH1cblxuICBkZXNlbGVjdE1lc3NhZ2VUb1F1b3RlKCkge1xuICAgIHRoaXMuY2hhbm5lbFNlcnZpY2Uuc2VsZWN0TWVzc2FnZVRvUXVvdGUodW5kZWZpbmVkKTtcbiAgfVxuXG4gIGRlc2VsZWN0TWVzc2FnZVRvRWRpdCgpIHtcbiAgICB0aGlzLm1lc3NhZ2VBY3Rpb25zU2VydmljZS5tZXNzYWdlVG9FZGl0JC5uZXh0KHVuZGVmaW5lZCk7XG4gIH1cblxuICBnZXRFbW9qaVBpY2tlckNvbnRleHQoKTogRW1vamlQaWNrZXJDb250ZXh0IHtcbiAgICByZXR1cm4ge1xuICAgICAgZW1vamlJbnB1dCQ6IHRoaXMuZW1vamlJbnB1dFNlcnZpY2UuZW1vamlJbnB1dCQsXG4gICAgfTtcbiAgfVxuXG4gIGdldEF0dGFjaG1lbnRQcmV2aWV3TGlzdENvbnRleHQoKTogQXR0YWNobWVudFByZXZpZXdMaXN0Q29udGV4dCB7XG4gICAgcmV0dXJuIHtcbiAgICAgIGF0dGFjaG1lbnRVcGxvYWRzJDogdGhpcy5hdHRhY2htZW50U2VydmljZS5hdHRhY2htZW50VXBsb2FkcyQsXG4gICAgICBkZWxldGVVcGxvYWRIYW5kbGVyOiB0aGlzLmRlbGV0ZVVwbG9hZC5iaW5kKHRoaXMpLFxuICAgICAgcmV0cnlVcGxvYWRIYW5kbGVyOiB0aGlzLnJldHJ5VXBsb2FkLmJpbmQodGhpcyksXG4gICAgICBzZXJ2aWNlOiB0aGlzLmF0dGFjaG1lbnRTZXJ2aWNlLFxuICAgIH07XG4gIH1cblxuICBnZXRBdHRhY2htZW50VXBsb2FkQ29udGV4dCgpOiBDdXN0b21BdHRhY2htZW50VXBsb2FkQ29udGV4dCB7XG4gICAgcmV0dXJuIHtcbiAgICAgIGlzTXVsdGlwbGVGaWxlVXBsb2FkRW5hYmxlZDogdGhpcy5pc011bHRpcGxlRmlsZVVwbG9hZEVuYWJsZWQsXG4gICAgICBhdHRhY2htZW50U2VydmljZTogdGhpcy5hdHRhY2htZW50U2VydmljZSxcbiAgICB9O1xuICB9XG5cbiAgZ2V0UXVvdGVkTWVzc2FnZVRleHRDb250ZXh0KCk6IE1lc3NhZ2VUZXh0Q29udGV4dCB7XG4gICAgcmV0dXJuIHtcbiAgICAgIG1lc3NhZ2U6IHRoaXMucXVvdGVkTWVzc2FnZSxcbiAgICAgIGlzUXVvdGVkOiB0cnVlLFxuICAgICAgc2hvdWxkVHJhbnNsYXRlOiB0cnVlLFxuICAgIH07XG4gIH1cblxuICBhc3luYyBzdGFydFZvaWNlUmVjb3JkaW5nKCkge1xuICAgIGF3YWl0IHRoaXMuYXVkaW9SZWNvcmRlcj8uc3RhcnQoKTtcbiAgICBpZiAodGhpcy5hdWRpb1JlY29yZGVyPy5pc1JlY29yZGluZykge1xuICAgICAgdGhpcy52b2ljZVJlY29yZGVyU2VydmljZS5pc1JlY29yZGVyVmlzaWJsZSQubmV4dCh0cnVlKTtcbiAgICB9XG4gIH1cblxuICBhc3luYyB2b2ljZVJlY29yZGluZ1JlYWR5KHJlY29yZGluZzogQXVkaW9SZWNvcmRpbmcpIHtcbiAgICB0cnkge1xuICAgICAgYXdhaXQgdGhpcy5hdHRhY2htZW50U2VydmljZS51cGxvYWRWb2ljZVJlY29yZGluZyhyZWNvcmRpbmcpO1xuICAgICAgaWYgKHRoaXMuY29uZmlnU2VydmljZS5zZW5kVm9pY2VSZWNvcmRpbmdJbW1lZGlhdGVseSkge1xuICAgICAgICBhd2FpdCB0aGlzLm1lc3NhZ2VTZW50KCk7XG4gICAgICB9XG4gICAgfSBmaW5hbGx5IHtcbiAgICAgIHRoaXMudm9pY2VSZWNvcmRlclNlcnZpY2UuaXNSZWNvcmRlclZpc2libGUkLm5leHQoZmFsc2UpO1xuICAgIH1cbiAgfVxuXG4gIGdldCBpc1VwZGF0ZSgpIHtcbiAgICByZXR1cm4gISF0aGlzLm1lc3NhZ2U7XG4gIH1cblxuICBwcml2YXRlIGRlbGV0ZVVwbG9hZCh1cGxvYWQ6IEF0dGFjaG1lbnRVcGxvYWQpIHtcbiAgICBpZiAodGhpcy5pc1VwZGF0ZSkge1xuICAgICAgLy8gRGVsYXkgZGVsZXRlIHRvIGF2b2lkIG1vZGFsIGRldGVjdGluZyB0aGlzIGNsaWNrIGFzIG91dHNpZGUgY2xpY2tcbiAgICAgIHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgICB2b2lkIHRoaXMuYXR0YWNobWVudFNlcnZpY2UuZGVsZXRlQXR0YWNobWVudCh1cGxvYWQpO1xuICAgICAgfSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHZvaWQgdGhpcy5hdHRhY2htZW50U2VydmljZS5kZWxldGVBdHRhY2htZW50KHVwbG9hZCk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSByZXRyeVVwbG9hZChmaWxlOiBGaWxlKSB7XG4gICAgdm9pZCB0aGlzLmF0dGFjaG1lbnRTZXJ2aWNlLnJldHJ5QXR0YWNobWVudFVwbG9hZChmaWxlKTtcbiAgfVxuXG4gIHByaXZhdGUgY2xlYXJGaWxlSW5wdXQoKSB7XG4gICAgdGhpcy5maWxlSW5wdXQubmF0aXZlRWxlbWVudC52YWx1ZSA9ICcnO1xuICB9XG5cbiAgcHJpdmF0ZSBpbml0VGV4dGFyZWEoKSB7XG4gICAgLy8gY2xlYW51cCBwcmV2aW91c2x5IGJ1aWx0IHRleHRhcmVhXG4gICAgaWYgKCF0aGlzLmNhblNlbmRNZXNzYWdlcykge1xuICAgICAgdGhpcy50ZXh0YXJlYVJlZiA9IHVuZGVmaW5lZDtcbiAgICB9XG5cbiAgICBpZiAoIXRoaXMuY2FuU2VuZE1lc3NhZ2VzIHx8IHRoaXMudGV4dGFyZWFSZWYgfHwgIXRoaXMudGV4dGFyZWFBbmNob3IpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zdCBjb21wb25lbnRGYWN0b3J5ID1cbiAgICAgIHRoaXMuY29tcG9uZW50RmFjdG9yeVJlc29sdmVyLnJlc29sdmVDb21wb25lbnRGYWN0b3J5KHRoaXMudGV4dGFyZWFUeXBlKTtcbiAgICB0aGlzLnRleHRhcmVhUmVmID1cbiAgICAgIHRoaXMudGV4dGFyZWFBbmNob3Iudmlld0NvbnRhaW5lclJlZi5jcmVhdGVDb21wb25lbnQ8VGV4dGFyZWFJbnRlcmZhY2U+KFxuICAgICAgICBjb21wb25lbnRGYWN0b3J5XG4gICAgICApO1xuICAgIHRoaXMuY2RSZWYuZGV0ZWN0Q2hhbmdlcygpO1xuICB9XG5cbiAgcHJpdmF0ZSBzZXRDYW5TZW5kTWVzc2FnZXMoKSB7XG4gICAgY29uc3QgY2FwYWJpbGl0aWVzID0gdGhpcy5jaGFubmVsPy5kYXRhPy5vd25fY2FwYWJpbGl0aWVzIGFzIHN0cmluZ1tdO1xuICAgIGlmICghY2FwYWJpbGl0aWVzKSB7XG4gICAgICB0aGlzLmNhblNlbmRNZXNzYWdlcyA9IGZhbHNlO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLmNhblNlbmRNZXNzYWdlcyA9XG4gICAgICAgIGNhcGFiaWxpdGllcy5pbmRleE9mKFxuICAgICAgICAgIHRoaXMubW9kZSA9PT0gJ21haW4nID8gJ3NlbmQtbWVzc2FnZScgOiAnc2VuZC1yZXBseSdcbiAgICAgICAgKSAhPT0gLTEgfHwgdGhpcy5pc1VwZGF0ZTtcbiAgICB9XG4gICAgaWYgKHRoaXMuaXNWaWV3SW5pdGVkKSB7XG4gICAgICB0aGlzLmNkUmVmLmRldGVjdENoYW5nZXMoKTtcbiAgICAgIHRoaXMuaW5pdFRleHRhcmVhKCk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBnZXQgcGFyZW50TWVzc2FnZUlkKCkge1xuICAgIGxldCBwYXJlbnRNZXNzYWdlSWQ6IHN0cmluZyB8IHVuZGVmaW5lZCA9IHVuZGVmaW5lZDtcbiAgICBpZiAodGhpcy5tb2RlID09PSAndGhyZWFkJykge1xuICAgICAgdGhpcy5jaGFubmVsU2VydmljZS5hY3RpdmVQYXJlbnRNZXNzYWdlSWQkXG4gICAgICAgIC5waXBlKGZpcnN0KCkpXG4gICAgICAgIC5zdWJzY3JpYmUoKGlkKSA9PiAocGFyZW50TWVzc2FnZUlkID0gaWQpKTtcbiAgICB9XG5cbiAgICByZXR1cm4gcGFyZW50TWVzc2FnZUlkO1xuICB9XG5cbiAgcHJpdmF0ZSBzdGFydENvb2xkb3duKGNvb2xkb3duOiBudW1iZXIpIHtcbiAgICB0aGlzLnRleHRhcmVhUGxhY2Vob2xkZXIgPSB0aGlzLnNsb3dNb2RlVGV4dGFyZWFQbGFjZWhvbGRlcjtcbiAgICB0aGlzLmlzQ29vbGRvd25JblByb2dyZXNzID0gdHJ1ZTtcbiAgICB0aGlzLmNvb2xkb3duJCA9IHRpbWVyKDAsIDEwMDApLnBpcGUoXG4gICAgICB0YWtlKGNvb2xkb3duICsgMSksXG4gICAgICBtYXAoKHYpID0+IGNvb2xkb3duIC0gdiksXG4gICAgICB0YXAoKHYpID0+IHtcbiAgICAgICAgaWYgKHYgPT09IDApIHtcbiAgICAgICAgICB0aGlzLnN0b3BDb29sZG93bigpO1xuICAgICAgICB9XG4gICAgICB9KVxuICAgICk7XG4gIH1cblxuICBwcml2YXRlIHN0b3BDb29sZG93bigpIHtcbiAgICB0aGlzLmNvb2xkb3duJCA9IHVuZGVmaW5lZDtcbiAgICB0aGlzLmlzQ29vbGRvd25JblByb2dyZXNzID0gZmFsc2U7XG4gICAgdGhpcy50ZXh0YXJlYVBsYWNlaG9sZGVyID0gdGhpcy5kZWZhdWx0VGV4dGFyZWFQbGFjZWhvbGRlcjtcbiAgfVxuXG4gIHByaXZhdGUgY2hlY2tJZkluRWRpdE1vZGUoKSB7XG4gICAgaWYgKCF0aGlzLndhdGNoRm9yTWVzc2FnZVRvRWRpdCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBpZiAoIXRoaXMubWVzc2FnZVRvRWRpdCAmJiB0aGlzLm1lc3NhZ2UpIHtcbiAgICAgIHRoaXMubWVzc2FnZSA9IHVuZGVmaW5lZDtcbiAgICAgIHRoaXMubWVzc2FnZVRvVXBkYXRlQ2hhbmdlZCgpO1xuICAgICAgaWYgKHRoaXMuaXNWaWV3SW5pdGVkKSB7XG4gICAgICAgIHRoaXMuY2RSZWYuZGV0ZWN0Q2hhbmdlcygpO1xuICAgICAgfVxuICAgIH1cbiAgICBpZiAoXG4gICAgICB0aGlzLm1lc3NhZ2VUb0VkaXQgJiZcbiAgICAgICgodGhpcy5tb2RlID09PSAnbWFpbicgJiYgIXRoaXMubWVzc2FnZVRvRWRpdC5wYXJlbnRfaWQpIHx8XG4gICAgICAgICh0aGlzLm1vZGUgPT09ICd0aHJlYWQnICYmIHRoaXMubWVzc2FnZVRvRWRpdC5wYXJlbnRfaWQpKVxuICAgICkge1xuICAgICAgdGhpcy5tZXNzYWdlID0gdGhpcy5tZXNzYWdlVG9FZGl0O1xuICAgICAgdGhpcy5tZXNzYWdlVG9VcGRhdGVDaGFuZ2VkKCk7XG4gICAgICBpZiAodGhpcy5pc1ZpZXdJbml0ZWQpIHtcbiAgICAgICAgdGhpcy5jZFJlZi5kZXRlY3RDaGFuZ2VzKCk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBtZXNzYWdlVG9VcGRhdGVDaGFuZ2VkKCkge1xuICAgIHRoaXMuYXR0YWNobWVudFNlcnZpY2UucmVzZXRBdHRhY2htZW50VXBsb2FkcygpO1xuICAgIHRoaXMuc2V0Q2FuU2VuZE1lc3NhZ2VzKCk7XG4gICAgaWYgKHRoaXMuaXNVcGRhdGUpIHtcbiAgICAgIHRoaXMuYXR0YWNobWVudFNlcnZpY2UuY3JlYXRlRnJvbUF0dGFjaG1lbnRzKFxuICAgICAgICB0aGlzLm1lc3NhZ2UhLmF0dGFjaG1lbnRzIHx8IFtdXG4gICAgICApO1xuICAgICAgdGhpcy50ZXh0YXJlYVZhbHVlID0gdGhpcy5tZXNzYWdlIS50ZXh0IHx8ICcnO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLnRleHRhcmVhVmFsdWUgPSAnJztcbiAgICB9XG4gIH1cbn1cbiIsIjxkaXZcbiAgY2xhc3M9XCJzdHItY2hhdF9fbWVzc2FnZS1pbnB1dCBzdHItY2hhdC1hbmd1bGFyX19tZXNzYWdlLWlucHV0XCJcbiAgW3N0eWxlLmRpc3BsYXldPVwiaXNWb2ljZVJlY29yZGluZyA/ICdub25lJyA6ICdmbGV4J1wiXG4+XG4gIDxkaXYgKm5nSWY9XCJxdW90ZWRNZXNzYWdlXCIgY2xhc3M9XCJzdHItY2hhdF9fcXVvdGVkLW1lc3NhZ2UtcHJldmlldy1oZWFkZXJcIj5cbiAgICA8ZGl2IGNsYXNzPVwic3RyLWNoYXRfX3F1b3RlZC1tZXNzYWdlLXJlcGx5LXRvLW1lc3NhZ2VcIj5cbiAgICAgIHt7IFwic3RyZWFtQ2hhdC5SZXBseSB0byBNZXNzYWdlXCIgfCB0cmFuc2xhdGUgfX1cbiAgICA8L2Rpdj5cbiAgICA8YnV0dG9uXG4gICAgICBjbGFzcz1cInN0ci1jaGF0X19xdW90ZWQtbWVzc2FnZS1yZW1vdmVcIlxuICAgICAgZGF0YS10ZXN0aWQ9XCJyZW1vdmUtcXVvdGVcIlxuICAgICAgKGNsaWNrKT1cImRlc2VsZWN0TWVzc2FnZVRvUXVvdGUoKVwiXG4gICAgICAoa2V5dXAuZW50ZXIpPVwiZGVzZWxlY3RNZXNzYWdlVG9RdW90ZSgpXCJcbiAgICA+XG4gICAgICA8c3RyZWFtLWljb24tcGxhY2Vob2xkZXIgaWNvbj1cImNsb3NlXCI+PC9zdHJlYW0taWNvbi1wbGFjZWhvbGRlcj5cbiAgICA8L2J1dHRvbj5cbiAgPC9kaXY+XG4gIDxkaXYgKm5nSWY9XCJpc1VwZGF0ZVwiIGNsYXNzPVwic3RyLWNoYXRfX3F1b3RlZC1tZXNzYWdlLXByZXZpZXctaGVhZGVyXCI+XG4gICAgPGRpdiBjbGFzcz1cInN0ci1jaGF0X19xdW90ZWQtbWVzc2FnZS1yZXBseS10by1tZXNzYWdlXCI+XG4gICAgICB7eyBcInN0cmVhbUNoYXQuRWRpdCBNZXNzYWdlXCIgfCB0cmFuc2xhdGUgfX1cbiAgICA8L2Rpdj5cbiAgICA8YnV0dG9uXG4gICAgICBjbGFzcz1cInN0ci1jaGF0X19xdW90ZWQtbWVzc2FnZS1yZW1vdmVcIlxuICAgICAgZGF0YS10ZXN0aWQ9XCJyZW1vdmUtcXVvdGVcIlxuICAgICAgKGNsaWNrKT1cImRlc2VsZWN0TWVzc2FnZVRvRWRpdCgpXCJcbiAgICAgIChrZXl1cC5lbnRlcik9XCJkZXNlbGVjdE1lc3NhZ2VUb0VkaXQoKVwiXG4gICAgPlxuICAgICAgPHN0cmVhbS1pY29uLXBsYWNlaG9sZGVyIGljb249XCJjbG9zZVwiPjwvc3RyZWFtLWljb24tcGxhY2Vob2xkZXI+XG4gICAgPC9idXR0b24+XG4gIDwvZGl2PlxuICA8bmctY29udGFpbmVyICpuZ0lmPVwiY2FuU2VuZE1lc3NhZ2VzOyBlbHNlIG5vdEFsbG93ZWRcIj5cbiAgICA8ZGl2XG4gICAgICBjbGFzcz1cInN0ci1jaGF0X19tZXNzYWdlLWlucHV0LWlubmVyIHN0ci1jaGF0LWFuZ3VsYXJfX21lc3NhZ2UtaW5wdXQtaW5uZXJcIlxuICAgID5cbiAgICAgIDxuZy1jb250ZW50IHNlbGVjdD1cIlttZXNzYWdlLWlucHV0LXN0YXJ0XVwiPjwvbmctY29udGVudD5cbiAgICAgIDxuZy1jb250YWluZXJcbiAgICAgICAgKm5nSWY9XCJpc0ZpbGVVcGxvYWRFbmFibGVkICYmIGlzRmlsZVVwbG9hZEF1dGhvcml6ZWQgJiYgY2FuU2VuZE1lc3NhZ2VzXCJcbiAgICAgID5cbiAgICAgICAgPG5nLWNvbnRhaW5lclxuICAgICAgICAgICpuZ1RlbXBsYXRlT3V0bGV0PVwiXG4gICAgICAgICAgICBjdXN0b21BdHRhY2htZW50VXBsb2FkVGVtcGxhdGUgfHwgZGVmYXVsdEF0dGFjaG1lbnRVcGxvYWQ7XG4gICAgICAgICAgICBjb250ZXh0OiBnZXRBdHRhY2htZW50VXBsb2FkQ29udGV4dCgpXG4gICAgICAgICAgXCJcbiAgICAgICAgPjwvbmctY29udGFpbmVyPlxuICAgICAgICA8bmctdGVtcGxhdGUgI2RlZmF1bHRBdHRhY2htZW50VXBsb2FkPlxuICAgICAgICAgIDxkaXZcbiAgICAgICAgICAgIGNsYXNzPVwic3RyLWNoYXRfX2ZpbGUtaW5wdXQtY29udGFpbmVyXCJcbiAgICAgICAgICAgIGRhdGEtdGVzdGlkPVwiZmlsZS11cGxvYWQtYnV0dG9uXCJcbiAgICAgICAgICA+XG4gICAgICAgICAgICA8aW5wdXRcbiAgICAgICAgICAgICAgI2ZpbGVJbnB1dFxuICAgICAgICAgICAgICB0eXBlPVwiZmlsZVwiXG4gICAgICAgICAgICAgIGNsYXNzPVwic3RyLWNoYXRfX2ZpbGUtaW5wdXRcIlxuICAgICAgICAgICAgICBkYXRhLXRlc3RpZD1cImZpbGUtaW5wdXRcIlxuICAgICAgICAgICAgICBbbXVsdGlwbGVdPVwiaXNNdWx0aXBsZUZpbGVVcGxvYWRFbmFibGVkXCJcbiAgICAgICAgICAgICAgaWQ9XCJ7eyBmaWxlSW5wdXRJZCB9fVwiXG4gICAgICAgICAgICAgIFtkaXNhYmxlZF09XCJcbiAgICAgICAgICAgICAgICAoYXR0YWNobWVudFNlcnZpY2UuYXR0YWNobWVudHNDb3VudGVyJCB8IGFzeW5jKSEgPj1cbiAgICAgICAgICAgICAgICBhdHRhY2htZW50U2VydmljZS5tYXhOdW1iZXJPZkF0dGFjaG1lbnRzXG4gICAgICAgICAgICAgIFwiXG4gICAgICAgICAgICAgIChjaGFuZ2UpPVwiZmlsZXNTZWxlY3RlZChmaWxlSW5wdXQuZmlsZXMpXCJcbiAgICAgICAgICAgIC8+XG4gICAgICAgICAgICA8bGFiZWwgY2xhc3M9XCJzdHItY2hhdF9fZmlsZS1pbnB1dC1sYWJlbFwiIGZvcj1cInt7IGZpbGVJbnB1dElkIH19XCI+XG4gICAgICAgICAgICAgIDxzdHJlYW0taWNvbi1wbGFjZWhvbGRlciBpY29uPVwiYXR0YWNoXCI+PC9zdHJlYW0taWNvbi1wbGFjZWhvbGRlcj5cbiAgICAgICAgICAgIDwvbGFiZWw+XG4gICAgICAgICAgPC9kaXY+XG4gICAgICAgIDwvbmctdGVtcGxhdGU+XG4gICAgICA8L25nLWNvbnRhaW5lcj5cbiAgICAgIDxkaXYgY2xhc3M9XCJzdHItY2hhdF9fbWVzc2FnZS10ZXh0YXJlYS1jb250YWluZXJcIj5cbiAgICAgICAgPGRpdlxuICAgICAgICAgICpuZ0lmPVwicXVvdGVkTWVzc2FnZVwiXG4gICAgICAgICAgZGF0YS10ZXN0aWQ9XCJxdW90ZWQtbWVzc2FnZS1jb250YWluZXJcIlxuICAgICAgICAgIGNsYXNzPVwic3RyLWNoYXRfX3F1b3RlZC1tZXNzYWdlLXByZXZpZXdcIlxuICAgICAgICA+XG4gICAgICAgICAgPHN0cmVhbS1hdmF0YXItcGxhY2Vob2xkZXJcbiAgICAgICAgICAgIGRhdGEtdGVzdGlkPVwicW91dGVkLW1lc3NhZ2UtYXZhdGFyXCJcbiAgICAgICAgICAgIGNsYXNzPVwic3RyLWNoYXQtYW5ndWxhcl9fYXZhdGFyLWhvc3Qgc3RyLWNoYXRfX21lc3NhZ2Utc2VuZGVyLWF2YXRhclwiXG4gICAgICAgICAgICB0eXBlPVwidXNlclwiXG4gICAgICAgICAgICBsb2NhdGlvbj1cInF1b3RlZC1tZXNzYWdlLXNlbmRlclwiXG4gICAgICAgICAgICBbaW1hZ2VVcmxdPVwicXVvdGVkTWVzc2FnZS51c2VyPy5pbWFnZVwiXG4gICAgICAgICAgICBbbmFtZV09XCJxdW90ZWRNZXNzYWdlLnVzZXI/Lm5hbWUgfHwgcXVvdGVkTWVzc2FnZS51c2VyPy5pZFwiXG4gICAgICAgICAgICBbdXNlcl09XCJxdW90ZWRNZXNzYWdlLnVzZXIgfHwgdW5kZWZpbmVkXCJcbiAgICAgICAgICA+PC9zdHJlYW0tYXZhdGFyLXBsYWNlaG9sZGVyPlxuICAgICAgICAgIDxkaXZcbiAgICAgICAgICAgIGNsYXNzPVwicXVvdGVkLW1lc3NhZ2UtcHJldmlldy1jb250ZW50LWlubmVyIHN0ci1jaGF0X19xdW90ZWQtbWVzc2FnZS1idWJibGVcIlxuICAgICAgICAgID5cbiAgICAgICAgICAgIDxzdHJlYW0tYXR0YWNobWVudC1saXN0XG4gICAgICAgICAgICAgICpuZ0lmPVwiXG4gICAgICAgICAgICAgICAgcXVvdGVkTWVzc2FnZT8uYXR0YWNobWVudHMgJiYgcXVvdGVkTWVzc2FnZT8uYXR0YWNobWVudHM/Lmxlbmd0aFxuICAgICAgICAgICAgICBcIlxuICAgICAgICAgICAgICBbYXR0YWNobWVudHNdPVwicXVvdGVkTWVzc2FnZUF0dGFjaG1lbnRzXCJcbiAgICAgICAgICAgICAgW21lc3NhZ2VJZF09XCJxdW90ZWRNZXNzYWdlLmlkXCJcbiAgICAgICAgICAgID48L3N0cmVhbS1hdHRhY2htZW50LWxpc3Q+XG4gICAgICAgICAgICA8ZGl2IGNsYXNzPVwic3RyLWNoYXRfX3F1b3RlZC1tZXNzYWdlLXRleHRcIj5cbiAgICAgICAgICAgICAgPG5nLWNvbnRhaW5lclxuICAgICAgICAgICAgICAgICpuZ1RlbXBsYXRlT3V0bGV0PVwiXG4gICAgICAgICAgICAgICAgICAoY3VzdG9tVGVtcGxhdGVzU2VydmljZS5tZXNzYWdlVGV4dFRlbXBsYXRlJCB8IGFzeW5jKSB8fFxuICAgICAgICAgICAgICAgICAgICBkZWZhdWx0VGV4dDtcbiAgICAgICAgICAgICAgICAgIGNvbnRleHQ6IGdldFF1b3RlZE1lc3NhZ2VUZXh0Q29udGV4dCgpXG4gICAgICAgICAgICAgICAgXCJcbiAgICAgICAgICAgICAgPjwvbmctY29udGFpbmVyPlxuICAgICAgICAgICAgICA8bmctdGVtcGxhdGVcbiAgICAgICAgICAgICAgICAjZGVmYXVsdFRleHRcbiAgICAgICAgICAgICAgICBsZXQtbWVzc2FnZT1cIm1lc3NhZ2VcIlxuICAgICAgICAgICAgICAgIGxldC1pc1F1b3RlZD1cImlzUXVvdGVkXCJcbiAgICAgICAgICAgICAgICBsZXQtc2hvdWxkVHJhbnNsYXRlPVwic2hvdWxkVHJhbnNsYXRlXCJcbiAgICAgICAgICAgICAgPlxuICAgICAgICAgICAgICAgIDxzdHJlYW0tbWVzc2FnZS10ZXh0XG4gICAgICAgICAgICAgICAgICBbbWVzc2FnZV09XCJtZXNzYWdlXCJcbiAgICAgICAgICAgICAgICAgIFtpc1F1b3RlZF09XCJpc1F1b3RlZFwiXG4gICAgICAgICAgICAgICAgICBbc2hvdWxkVHJhbnNsYXRlXT1cInNob3VsZFRyYW5zbGF0ZVwiXG4gICAgICAgICAgICAgICAgICBkYXRhLXRlc3RpZD1cInF1b3RlZC1tZXNzYWdlLXRleHRcIlxuICAgICAgICAgICAgICAgID48L3N0cmVhbS1tZXNzYWdlLXRleHQ+XG4gICAgICAgICAgICAgIDwvbmctdGVtcGxhdGU+XG4gICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgPC9kaXY+XG4gICAgICAgIDxuZy10ZW1wbGF0ZVxuICAgICAgICAgICNkZWZhdWx0QXR0YWNobWVudHNQcmV2aWV3XG4gICAgICAgICAgbGV0LWF0dGFjaG1lbnRVcGxvYWRzJD1cImF0dGFjaG1lbnRVcGxvYWRzJFwiXG4gICAgICAgICAgbGV0LXJldHJ5VXBsb2FkSGFuZGxlcj1cInJldHJ5VXBsb2FkSGFuZGxlclwiXG4gICAgICAgICAgbGV0LWRlbGV0ZVVwbG9hZEhhbmRsZXI9XCJkZWxldGVVcGxvYWRIYW5kbGVyXCJcbiAgICAgICAgPlxuICAgICAgICAgIDxzdHJlYW0tYXR0YWNobWVudC1wcmV2aWV3LWxpc3RcbiAgICAgICAgICAgIGNsYXNzPVwic3RyLWNoYXRfX2F0dGFjaG1lbnQtcHJldmlldy1saXN0LWFuZ3VsYXItaG9zdFwiXG4gICAgICAgICAgICBbYXR0YWNobWVudFVwbG9hZHMkXT1cImF0dGFjaG1lbnRVcGxvYWRzJFwiXG4gICAgICAgICAgICAocmV0cnlBdHRhY2htZW50VXBsb2FkKT1cInJldHJ5VXBsb2FkSGFuZGxlcigkZXZlbnQpXCJcbiAgICAgICAgICAgIChkZWxldGVBdHRhY2htZW50KT1cImRlbGV0ZVVwbG9hZEhhbmRsZXIoJGV2ZW50KVwiXG4gICAgICAgICAgPjwvc3RyZWFtLWF0dGFjaG1lbnQtcHJldmlldy1saXN0PlxuICAgICAgICA8L25nLXRlbXBsYXRlPlxuICAgICAgICA8bmctY29udGFpbmVyXG4gICAgICAgICAgKm5nVGVtcGxhdGVPdXRsZXQ9XCJcbiAgICAgICAgICAgIGF0dGFjaG1lbnRQcmV2aWV3TGlzdFRlbXBsYXRlIHx8IGRlZmF1bHRBdHRhY2htZW50c1ByZXZpZXc7XG4gICAgICAgICAgICBjb250ZXh0OiBnZXRBdHRhY2htZW50UHJldmlld0xpc3RDb250ZXh0KClcbiAgICAgICAgICBcIlxuICAgICAgICA+PC9uZy1jb250YWluZXI+XG4gICAgICAgIDxkaXYgY2xhc3M9XCJzdHItY2hhdF9fbWVzc2FnZS10ZXh0YXJlYS13aXRoLWVtb2ppLXBpY2tlclwiPlxuICAgICAgICAgIDxuZy1jb250YWluZXJcbiAgICAgICAgICAgIHN0cmVhbVRleHRhcmVhXG4gICAgICAgICAgICBbY29tcG9uZW50UmVmXT1cInRleHRhcmVhUmVmXCJcbiAgICAgICAgICAgIFthcmVNZW50aW9uc0VuYWJsZWRdPVwiYXJlTWVudGlvbnNFbmFibGVkXCJcbiAgICAgICAgICAgIFttZW50aW9uU2NvcGVdPVwibWVudGlvblNjb3BlXCJcbiAgICAgICAgICAgIFtpbnB1dE1vZGVdPVwiaW5wdXRNb2RlXCJcbiAgICAgICAgICAgIFthdXRvRm9jdXNdPVwiYXV0b0ZvY3VzXCJcbiAgICAgICAgICAgIFtwbGFjZWhvbGRlcl09XCJ0ZXh0YXJlYVBsYWNlaG9sZGVyXCJcbiAgICAgICAgICAgIFsodmFsdWUpXT1cInRleHRhcmVhVmFsdWVcIlxuICAgICAgICAgICAgKHZhbHVlQ2hhbmdlKT1cInR5cGluZ1N0YXJ0JC5uZXh0KClcIlxuICAgICAgICAgICAgKHNlbmQpPVwibWVzc2FnZVNlbnQoKVwiXG4gICAgICAgICAgICAodXNlck1lbnRpb25zKT1cIm1lbnRpb25lZFVzZXJzID0gJGV2ZW50XCJcbiAgICAgICAgICAgIChwYXN0ZUZyb21DbGlwYm9hcmQpPVwiaXRlbXNQYXN0ZWQoJGV2ZW50KVwiXG4gICAgICAgICAgPjwvbmctY29udGFpbmVyPlxuICAgICAgICAgIDxuZy1jb250YWluZXIgKm5nSWY9XCJlbW9qaVBpY2tlclRlbXBsYXRlXCIgZGF0YS10ZXN0aWQ9XCJlbW9qaS1waWNrZXJcIj5cbiAgICAgICAgICAgIDxuZy1jb250YWluZXJcbiAgICAgICAgICAgICAgKm5nVGVtcGxhdGVPdXRsZXQ9XCJcbiAgICAgICAgICAgICAgICBlbW9qaVBpY2tlclRlbXBsYXRlO1xuICAgICAgICAgICAgICAgIGNvbnRleHQ6IGdldEVtb2ppUGlja2VyQ29udGV4dCgpXG4gICAgICAgICAgICAgIFwiXG4gICAgICAgICAgICA+PC9uZy1jb250YWluZXI+XG4gICAgICAgICAgPC9uZy1jb250YWluZXI+XG4gICAgICAgIDwvZGl2PlxuICAgICAgPC9kaXY+XG4gICAgICA8YnV0dG9uXG4gICAgICAgICpuZ0lmPVwiY2FuU2VuZE1lc3NhZ2VzICYmICFpc0Nvb2xkb3duSW5Qcm9ncmVzcyAmJiBkaXNwbGF5U2VuZEJ1dHRvblwiXG4gICAgICAgIGRhdGEtdGVzdGlkPVwic2VuZC1idXR0b25cIlxuICAgICAgICBjbGFzcz1cInN0ci1jaGF0X19zZW5kLWJ1dHRvblwiXG4gICAgICAgIFtkaXNhYmxlZF09XCJcbiAgICAgICAgICAoYXR0YWNobWVudFVwbG9hZEluUHJvZ3Jlc3NDb3VudGVyJCB8IGFzeW5jKSEgPiAwIHx8XG4gICAgICAgICAgKGF0dGFjaG1lbnRTZXJ2aWNlLmF0dGFjaG1lbnRzQ291bnRlciQgfCBhc3luYykhID5cbiAgICAgICAgICAgIGF0dGFjaG1lbnRTZXJ2aWNlLm1heE51bWJlck9mQXR0YWNobWVudHMgfHxcbiAgICAgICAgICAoIXRleHRhcmVhVmFsdWUgJiZcbiAgICAgICAgICAgIChhdHRhY2htZW50VXBsb2FkcyQgfCBhc3luYykhLmxlbmd0aCA9PT0gMCAmJlxuICAgICAgICAgICAgKGN1c3RvbUF0dGFjaG1lbnRzJCB8IGFzeW5jKSEubGVuZ3RoID09PSAwKVxuICAgICAgICBcIlxuICAgICAgICAoY2xpY2spPVwibWVzc2FnZVNlbnQoKVwiXG4gICAgICAgIChrZXl1cC5lbnRlcik9XCJtZXNzYWdlU2VudCgpXCJcbiAgICAgID5cbiAgICAgICAgPHN0cmVhbS1pY29uLXBsYWNlaG9sZGVyIGljb249XCJzZW5kXCI+PC9zdHJlYW0taWNvbi1wbGFjZWhvbGRlcj5cbiAgICAgIDwvYnV0dG9uPlxuICAgICAgPGRpdlxuICAgICAgICAqbmdJZj1cImlzQ29vbGRvd25JblByb2dyZXNzXCJcbiAgICAgICAgY2xhc3M9XCJzdHItY2hhdF9fbWVzc2FnZS1pbnB1dC1jb29sZG93blwiXG4gICAgICAgIGRhdGEtdGVzdGlkPVwiY29vbGRvd24tdGltZXJcIlxuICAgICAgPlxuICAgICAgICB7eyBjb29sZG93biQgfCBhc3luYyB9fVxuICAgICAgPC9kaXY+XG4gICAgICA8YnV0dG9uXG4gICAgICAgICpuZ0lmPVwiZGlzcGxheVZvaWNlUmVjb3JkaW5nQnV0dG9uXCJcbiAgICAgICAgY2xhc3M9XCJzdHItY2hhdF9fc3RhcnQtcmVjb3JkaW5nLWF1ZGlvLWJ1dHRvblwiXG4gICAgICAgIGRhdGEtdGVzdGlkPVwic3RhcnQtdm9pY2UtcmVjb3JkaW5nXCJcbiAgICAgICAgW2Rpc2FibGVkXT1cIlxuICAgICAgICAgIHZvaWNlUmVjb3JkZXJTZXJ2aWNlLmlzUmVjb3JkZXJWaXNpYmxlJC52YWx1ZSB8fFxuICAgICAgICAgIGF1ZGlvUmVjb3JkZXI/LmlzUmVjb3JkaW5nIHx8XG4gICAgICAgICAgKGF0dGFjaG1lbnRTZXJ2aWNlLmF0dGFjaG1lbnRzQ291bnRlciQgfCBhc3luYykhID49XG4gICAgICAgICAgICBhdHRhY2htZW50U2VydmljZS5tYXhOdW1iZXJPZkF0dGFjaG1lbnRzXG4gICAgICAgIFwiXG4gICAgICAgIChjbGljayk9XCJzdGFydFZvaWNlUmVjb3JkaW5nKClcIlxuICAgICAgICAoa2V5dXAuZW50ZXIpPVwic3RhcnRWb2ljZVJlY29yZGluZygpXCJcbiAgICAgID5cbiAgICAgICAgPHN0cmVhbS1pY29uLXBsYWNlaG9sZGVyIGljb249XCJtaWNcIj48L3N0cmVhbS1pY29uLXBsYWNlaG9sZGVyPlxuICAgICAgPC9idXR0b24+XG4gICAgICA8bmctY29udGVudCBzZWxlY3Q9XCJbbWVzc2FnZS1pbnB1dC1lbmRdXCI+PC9uZy1jb250ZW50PlxuICAgIDwvZGl2PlxuICA8L25nLWNvbnRhaW5lcj5cbiAgPG5nLXRlbXBsYXRlICNub3RBbGxvd2VkPlxuICAgIDxkaXZcbiAgICAgIGNsYXNzPVwic3RyLWNoYXRfX21lc3NhZ2UtaW5wdXQtbm90LWFsbG93ZWRcIlxuICAgICAgZGF0YS10ZXN0aWQ9XCJkaXNhYmxlZC10ZXh0YXJlYVwiXG4gICAgPlxuICAgICAge3sgZGlzYWJsZWRUZXh0YXJlYVRleHQgfCB0cmFuc2xhdGUgfX1cbiAgICA8L2Rpdj5cbiAgPC9uZy10ZW1wbGF0ZT5cbjwvZGl2PlxuPG5nLXRlbXBsYXRlXG4gICpuZ0lmPVwidm9pY2VSZWNvcmRlclJlZlwiXG4gIFtuZ1RlbXBsYXRlT3V0bGV0XT1cInZvaWNlUmVjb3JkZXJSZWZcIlxuICBbbmdUZW1wbGF0ZU91dGxldENvbnRleHRdPVwieyBzZXJ2aWNlOiB2b2ljZVJlY29yZGVyU2VydmljZSB9XCJcbj48L25nLXRlbXBsYXRlPlxuIl19