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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (165) hide show
  1. package/assets/i18n/en.d.ts +1 -0
  2. package/assets/version.d.ts +1 -1
  3. package/{esm2020 → esm2022}/assets/i18n/en.mjs +2 -1
  4. package/{esm2020 → esm2022}/assets/version.mjs +2 -2
  5. package/{esm2020 → esm2022}/lib/attachment-configuration.service.mjs +4 -4
  6. package/esm2022/lib/attachment-list/attachment-list.component.mjs +212 -0
  7. package/esm2022/lib/attachment-preview-list/attachment-preview-list.component.mjs +55 -0
  8. package/{esm2020 → esm2022}/lib/attachment.service.mjs +5 -5
  9. package/esm2022/lib/avatar/avatar.component.mjs +157 -0
  10. package/{esm2020 → esm2022}/lib/avatar-placeholder/avatar-placeholder.component.mjs +6 -6
  11. package/esm2022/lib/channel/channel.component.mjs +45 -0
  12. package/esm2022/lib/channel-header/channel-header.component.mjs +72 -0
  13. package/esm2022/lib/channel-list/channel-list.component.mjs +50 -0
  14. package/esm2022/lib/channel-preview/channel-preview.component.mjs +150 -0
  15. package/esm2022/lib/channel.service.mjs +1381 -0
  16. package/esm2022/lib/chat-client.service.mjs +227 -0
  17. package/{esm2020 → esm2022}/lib/custom-templates.service.mjs +5 -5
  18. package/{esm2020 → esm2022}/lib/date-parser.service.mjs +5 -5
  19. package/esm2022/lib/file-utils.mjs +35 -0
  20. package/{esm2020 → esm2022}/lib/get-channel-display-text.mjs +1 -1
  21. package/{esm2020 → esm2022}/lib/get-message-translation.mjs +1 -1
  22. package/{esm2020 → esm2022}/lib/icon/icon-placeholder/icon-placeholder.component.mjs +6 -6
  23. package/{esm2020 → esm2022}/lib/icon/icon.component.mjs +5 -5
  24. package/{esm2020 → esm2022}/lib/icon/icon.module.mjs +11 -11
  25. package/{esm2020 → esm2022}/lib/icon/loading-indicator/loading-indicator.component.mjs +5 -5
  26. package/{esm2020 → esm2022}/lib/icon/loading-indicator-placeholder/loading-indicator-placeholder.component.mjs +6 -6
  27. package/{esm2020 → esm2022}/lib/list-users.mjs +1 -1
  28. package/esm2022/lib/message/message.component.mjs +486 -0
  29. package/esm2022/lib/message-actions-box/message-actions-box.component.mjs +120 -0
  30. package/{esm2020 → esm2022}/lib/message-actions.service.mjs +5 -5
  31. package/esm2022/lib/message-bounce-prompt/message-bounce-prompt.component.mjs +71 -0
  32. package/{esm2020 → esm2022}/lib/message-input/autocomplete-textarea/autocomplete-textarea.component.mjs +6 -6
  33. package/{esm2020 → esm2022}/lib/message-input/emoji-input.service.mjs +5 -5
  34. package/{esm2020 → esm2022}/lib/message-input/message-input-config.service.mjs +5 -5
  35. package/esm2022/lib/message-input/message-input.component.mjs +507 -0
  36. package/{esm2020 → esm2022}/lib/message-input/textarea/textarea.component.mjs +5 -5
  37. package/{esm2020 → esm2022}/lib/message-input/textarea.directive.mjs +5 -5
  38. package/{esm2020 → esm2022}/lib/message-input/voice-recorder.service.mjs +5 -5
  39. package/{esm2020 → esm2022}/lib/message-list/group-styles.mjs +1 -1
  40. package/esm2022/lib/message-list/message-list.component.mjs +715 -0
  41. package/{esm2020 → esm2022}/lib/message-preview.mjs +1 -1
  42. package/esm2022/lib/message-reactions/message-reactions.component.mjs +165 -0
  43. package/esm2022/lib/message-reactions-selector/message-reactions-selector.component.mjs +57 -0
  44. package/{esm2020 → esm2022}/lib/message-reactions.service.mjs +5 -5
  45. package/{esm2020 → esm2022}/lib/message-text/message-text.component.mjs +6 -6
  46. package/esm2022/lib/message.service.mjs +43 -0
  47. package/{esm2020 → esm2022}/lib/modal/modal.component.mjs +6 -6
  48. package/{esm2020 → esm2022}/lib/notification/notification.component.mjs +6 -6
  49. package/esm2022/lib/notification-list/notification-list.component.mjs +33 -0
  50. package/{esm2020 → esm2022}/lib/notification.service.mjs +5 -5
  51. package/esm2022/lib/paginated-list/paginated-list.component.mjs +94 -0
  52. package/{esm2020 → esm2022}/lib/parse-date.mjs +1 -1
  53. package/{esm2020 → esm2022}/lib/read-by.mjs +1 -1
  54. package/esm2022/lib/stream-autocomplete-textarea.module.mjs +33 -0
  55. package/{esm2020 → esm2022}/lib/stream-avatar.module.mjs +5 -5
  56. package/{esm2020 → esm2022}/lib/stream-chat.module.mjs +59 -59
  57. package/{esm2020 → esm2022}/lib/stream-i18n.service.mjs +5 -5
  58. package/esm2022/lib/stream-textarea.module.mjs +31 -0
  59. package/{esm2020 → esm2022}/lib/theme.service.mjs +5 -5
  60. package/{esm2020 → esm2022}/lib/thread/thread.component.mjs +6 -6
  61. package/{esm2020 → esm2022}/lib/transliteration.service.mjs +5 -5
  62. package/esm2022/lib/types.mjs +2 -0
  63. package/{esm2020 → esm2022}/lib/user-list/user-list.component.mjs +5 -5
  64. package/esm2022/lib/virtualized-list.service.mjs +273 -0
  65. package/{esm2020 → esm2022}/lib/virtualized-message-list.service.mjs +1 -1
  66. package/{esm2020 → esm2022}/lib/voice-recorder/amplitude-recorder.service.mjs +5 -5
  67. package/{esm2020 → esm2022}/lib/voice-recorder/audio-recorder.service.mjs +5 -5
  68. package/{esm2020 → esm2022}/lib/voice-recorder/media-recorder.mjs +1 -1
  69. package/esm2022/lib/voice-recorder/mp3-transcoder.mjs +61 -0
  70. package/esm2022/lib/voice-recorder/transcoder.service.mjs +121 -0
  71. package/esm2022/lib/voice-recorder/voice-recorder-wavebar/voice-recorder-wavebar.component.mjs +32 -0
  72. package/esm2022/lib/voice-recorder/voice-recorder.component.mjs +80 -0
  73. package/{esm2020 → esm2022}/lib/voice-recorder/voice-recorder.module.mjs +9 -9
  74. package/esm2022/lib/voice-recording/voice-recording-wavebar/voice-recording-wavebar.component.mjs +112 -0
  75. package/esm2022/lib/voice-recording/voice-recording.component.mjs +91 -0
  76. package/{esm2020 → esm2022}/lib/voice-recording/voice-recording.module.mjs +5 -5
  77. package/{esm2020 → esm2022}/lib/wave-form-sampler.mjs +1 -1
  78. package/esm2022/public-api.mjs +82 -0
  79. package/{fesm2020 → fesm2022}/stream-chat-angular.mjs +857 -1140
  80. package/fesm2022/stream-chat-angular.mjs.map +1 -0
  81. package/lib/attachment-list/attachment-list.component.d.ts +2 -5
  82. package/lib/attachment-preview-list/attachment-preview-list.component.d.ts +2 -2
  83. package/lib/attachment.service.d.ts +1 -1
  84. package/lib/avatar/avatar.component.d.ts +4 -4
  85. package/lib/avatar-placeholder/avatar-placeholder.component.d.ts +1 -1
  86. package/lib/channel-list/channel-list.component.d.ts +1 -0
  87. package/lib/channel-preview/channel-preview.component.d.ts +3 -4
  88. package/lib/channel.service.d.ts +40 -106
  89. package/lib/chat-client.service.d.ts +1 -4
  90. package/lib/custom-templates.service.d.ts +10 -10
  91. package/lib/icon/icon-placeholder/icon-placeholder.component.d.ts +1 -1
  92. package/lib/icon/icon.component.d.ts +2 -2
  93. package/lib/message/message.component.d.ts +2 -2
  94. package/lib/message-actions-box/message-actions-box.component.d.ts +2 -3
  95. package/lib/message-actions.service.d.ts +1 -1
  96. package/lib/message-input/autocomplete-textarea/autocomplete-textarea.component.d.ts +2 -2
  97. package/lib/message-input/message-input.component.d.ts +2 -2
  98. package/lib/message-input/textarea/textarea.component.d.ts +1 -1
  99. package/lib/message-input/textarea.directive.d.ts +2 -2
  100. package/lib/message-list/group-styles.d.ts +1 -1
  101. package/lib/message-list/message-list.component.d.ts +2 -3
  102. package/lib/message-reactions/message-reactions.component.d.ts +2 -3
  103. package/lib/message-reactions-selector/message-reactions-selector.component.d.ts +1 -2
  104. package/lib/message-text/message-text.component.d.ts +2 -2
  105. package/lib/modal/modal.component.d.ts +1 -1
  106. package/lib/notification/notification.component.d.ts +1 -1
  107. package/lib/notification-list/notification-list.component.d.ts +0 -1
  108. package/lib/paginated-list/paginated-list.component.d.ts +5 -2
  109. package/lib/read-by.d.ts +1 -1
  110. package/lib/types.d.ts +98 -84
  111. package/lib/user-list/user-list.component.d.ts +1 -1
  112. package/lib/voice-recorder/amplitude-recorder.service.d.ts +2 -2
  113. package/lib/voice-recorder/media-recorder.d.ts +2 -2
  114. package/lib/voice-recorder/transcoder.service.d.ts +4 -4
  115. package/lib/voice-recorder/voice-recorder-wavebar/voice-recorder-wavebar.component.d.ts +0 -1
  116. package/lib/voice-recorder/voice-recorder.component.d.ts +2 -2
  117. package/lib/voice-recording/voice-recording-wavebar/voice-recording-wavebar.component.d.ts +3 -3
  118. package/lib/voice-recording/voice-recording.component.d.ts +1 -1
  119. package/package.json +15 -21
  120. package/public-api.d.ts +0 -1
  121. package/src/assets/i18n/en.ts +1 -0
  122. package/src/assets/version.ts +1 -1
  123. package/esm2020/lib/attachment-list/attachment-list.component.mjs +0 -224
  124. package/esm2020/lib/attachment-preview-list/attachment-preview-list.component.mjs +0 -55
  125. package/esm2020/lib/avatar/avatar.component.mjs +0 -160
  126. package/esm2020/lib/channel/channel.component.mjs +0 -45
  127. package/esm2020/lib/channel-header/channel-header.component.mjs +0 -72
  128. package/esm2020/lib/channel-list/channel-list.component.mjs +0 -47
  129. package/esm2020/lib/channel-preview/channel-preview.component.mjs +0 -155
  130. package/esm2020/lib/channel-query.mjs +0 -77
  131. package/esm2020/lib/channel.service.mjs +0 -1546
  132. package/esm2020/lib/chat-client.service.mjs +0 -238
  133. package/esm2020/lib/file-utils.mjs +0 -35
  134. package/esm2020/lib/message/message.component.mjs +0 -486
  135. package/esm2020/lib/message-actions-box/message-actions-box.component.mjs +0 -123
  136. package/esm2020/lib/message-bounce-prompt/message-bounce-prompt.component.mjs +0 -71
  137. package/esm2020/lib/message-input/message-input.component.mjs +0 -507
  138. package/esm2020/lib/message-list/message-list.component.mjs +0 -717
  139. package/esm2020/lib/message-reactions/message-reactions.component.mjs +0 -168
  140. package/esm2020/lib/message-reactions-selector/message-reactions-selector.component.mjs +0 -61
  141. package/esm2020/lib/message.service.mjs +0 -43
  142. package/esm2020/lib/notification-list/notification-list.component.mjs +0 -36
  143. package/esm2020/lib/paginated-list/paginated-list.component.mjs +0 -94
  144. package/esm2020/lib/stream-autocomplete-textarea.module.mjs +0 -33
  145. package/esm2020/lib/stream-textarea.module.mjs +0 -31
  146. package/esm2020/lib/types.mjs +0 -2
  147. package/esm2020/lib/virtualized-list.service.mjs +0 -271
  148. package/esm2020/lib/voice-recorder/mp3-transcoder.mjs +0 -61
  149. package/esm2020/lib/voice-recorder/transcoder.service.mjs +0 -121
  150. package/esm2020/lib/voice-recorder/voice-recorder-wavebar/voice-recorder-wavebar.component.mjs +0 -35
  151. package/esm2020/lib/voice-recorder/voice-recorder.component.mjs +0 -80
  152. package/esm2020/lib/voice-recording/voice-recording-wavebar/voice-recording-wavebar.component.mjs +0 -112
  153. package/esm2020/lib/voice-recording/voice-recording.component.mjs +0 -91
  154. package/esm2020/public-api.mjs +0 -83
  155. package/fesm2015/stream-chat-angular.mjs +0 -9152
  156. package/fesm2015/stream-chat-angular.mjs.map +0 -1
  157. package/fesm2020/stream-chat-angular.mjs.map +0 -1
  158. package/lib/channel-query.d.ts +0 -26
  159. /package/{esm2020 → esm2022}/lib/format-duration.mjs +0 -0
  160. /package/{esm2020 → esm2022}/lib/injection-tokens.mjs +0 -0
  161. /package/{esm2020 → esm2022}/lib/is-image-attachment.mjs +0 -0
  162. /package/{esm2020 → esm2022}/lib/is-on-separate-date.mjs +0 -0
  163. /package/{esm2020 → esm2022}/lib/is-safari.mjs +0 -0
  164. /package/{esm2020 → esm2022}/lib/message-input/textarea.interface.mjs +0 -0
  165. /package/{esm2020 → esm2022}/stream-chat-angular.mjs +0 -0
@@ -0,0 +1,212 @@
1
+ import { Component, EventEmitter, HostBinding, Input, Output, ViewChild, } from '@angular/core';
2
+ import prettybytes from 'pretty-bytes';
3
+ import { isImageAttachment } from '../is-image-attachment';
4
+ import * as i0 from "@angular/core";
5
+ import * as i1 from "../custom-templates.service";
6
+ import * as i2 from "../channel.service";
7
+ import * as i3 from "../attachment-configuration.service";
8
+ import * as i4 from "../message.service";
9
+ import * as i5 from "@angular/common";
10
+ import * as i6 from "../voice-recording/voice-recording.component";
11
+ import * as i7 from "../icon/icon-placeholder/icon-placeholder.component";
12
+ import * as i8 from "../modal/modal.component";
13
+ import * as i9 from "@ngx-translate/core";
14
+ /**
15
+ * The `AttachmentList` component displays the attachments of a message
16
+ */
17
+ export class AttachmentListComponent {
18
+ constructor(customTemplatesService, channelService, attachmentConfigurationService, messageService) {
19
+ this.customTemplatesService = customTemplatesService;
20
+ this.channelService = channelService;
21
+ this.attachmentConfigurationService = attachmentConfigurationService;
22
+ this.messageService = messageService;
23
+ /**
24
+ * The attachments to display
25
+ */
26
+ this.attachments = [];
27
+ /**
28
+ * Emits the state of the image carousel window
29
+ */
30
+ this.imageModalStateChange = new EventEmitter();
31
+ this.class = 'str-chat__attachment-list-angular-host';
32
+ this.orderedAttachments = [];
33
+ this.customAttachments = [];
34
+ this.imagesToView = [];
35
+ this.imagesToViewCurrentIndex = 0;
36
+ this.attachmentConfigurations = new Map();
37
+ this.subscriptions = [];
38
+ }
39
+ ngOnChanges(changes) {
40
+ if (changes.attachments) {
41
+ const builtInAttachments = [];
42
+ const customAttachments = [];
43
+ this.attachments.forEach((a) => {
44
+ if (this.messageService.isCustomAttachment(a)) {
45
+ customAttachments.push(a);
46
+ }
47
+ else {
48
+ builtInAttachments.push(a);
49
+ }
50
+ });
51
+ const images = builtInAttachments.filter(this.isImage);
52
+ const containsGallery = images.length >= 2;
53
+ this.orderedAttachments = [
54
+ ...(containsGallery ? this.createGallery(images) : images),
55
+ ...builtInAttachments.filter((a) => this.isVideo(a)),
56
+ ...builtInAttachments.filter((a) => this.isVoiceMessage(a)),
57
+ ...builtInAttachments.filter((a) => this.isFile(a)),
58
+ ];
59
+ this.attachmentConfigurations = new Map();
60
+ // Display link attachments only if there are no other attachments
61
+ // Giphy-s always sent without other attachments
62
+ if (this.orderedAttachments.length === 0) {
63
+ this.orderedAttachments.push(...builtInAttachments.filter((a) => this.isCard(a)));
64
+ }
65
+ this.customAttachments = customAttachments;
66
+ }
67
+ }
68
+ ngOnInit() {
69
+ this.subscriptions.push(this.customTemplatesService.customAttachmentListTemplate$.subscribe((t) => (this.customAttachmentsTemplate = t)));
70
+ }
71
+ ngOnDestroy() {
72
+ this.subscriptions.forEach((s) => s.unsubscribe());
73
+ }
74
+ isImage(attachment) {
75
+ return isImageAttachment(attachment);
76
+ }
77
+ isSvg(attachment) {
78
+ const filename = attachment.fallback || '';
79
+ return !!filename.toLowerCase().endsWith('.svg');
80
+ }
81
+ isFile(attachment) {
82
+ return attachment.type === 'file';
83
+ }
84
+ isGallery(attachment) {
85
+ return attachment.type === 'gallery';
86
+ }
87
+ isVideo(attachment) {
88
+ return (attachment.type === 'video' &&
89
+ attachment.asset_url &&
90
+ !attachment.og_scrape_url);
91
+ }
92
+ isCard(attachment) {
93
+ return (!attachment.type ||
94
+ (attachment.type === 'image' && !this.isImage(attachment)) ||
95
+ attachment.type === 'giphy' ||
96
+ (attachment.type === 'video' && attachment.og_scrape_url));
97
+ }
98
+ isVoiceMessage(attachment) {
99
+ return attachment.type === 'voiceRecording';
100
+ }
101
+ hasFileSize(attachment) {
102
+ return (attachment.file_size && Number.isFinite(Number(attachment.file_size)));
103
+ }
104
+ getFileSize(attachment) {
105
+ return prettybytes(Number(attachment.file_size));
106
+ }
107
+ getModalContext() {
108
+ return {
109
+ isOpen: this.imagesToView && this.imagesToView.length > 0,
110
+ isOpenChangeHandler: (isOpen) => (isOpen ? null : this.closeImageModal()),
111
+ content: this.modalContent,
112
+ };
113
+ }
114
+ trimUrl(url) {
115
+ if (url !== undefined && url !== null) {
116
+ const [trimmedUrl] = url
117
+ .replace(/^(?:https?:\/\/)?(?:www\.)?/i, '')
118
+ .split('/');
119
+ return trimmedUrl;
120
+ }
121
+ return null;
122
+ }
123
+ sendAction(action) {
124
+ void this.channelService.sendAction(this.messageId, {
125
+ [action.name]: action.value,
126
+ }, this.parentMessageId);
127
+ }
128
+ openImageModal(attachments, selectedIndex = 0) {
129
+ this.imageModalStateChange.next('opened');
130
+ this.imagesToView = attachments;
131
+ this.imagesToViewCurrentIndex = selectedIndex;
132
+ }
133
+ stepImages(dir) {
134
+ this.imagesToViewCurrentIndex += dir * 1;
135
+ }
136
+ getAttachmentContext(attachment) {
137
+ return { attachment };
138
+ }
139
+ getImageAttachmentConfiguration(attachment, type, element) {
140
+ const existingConfiguration = this.attachmentConfigurations.get(attachment);
141
+ if (existingConfiguration) {
142
+ return existingConfiguration;
143
+ }
144
+ const configuration = this.attachmentConfigurationService.getImageAttachmentConfiguration(attachment, type, element);
145
+ this.attachmentConfigurations.set(attachment, configuration);
146
+ return configuration;
147
+ }
148
+ getCarouselImageAttachmentConfiguration(attachment, element) {
149
+ return this.attachmentConfigurationService.getImageAttachmentConfiguration(attachment, 'carousel', element);
150
+ }
151
+ getVideoAttachmentConfiguration(attachment, element) {
152
+ const existingConfiguration = this.attachmentConfigurations.get(attachment);
153
+ if (existingConfiguration) {
154
+ return existingConfiguration;
155
+ }
156
+ const configuration = this.attachmentConfigurationService.getVideoAttachmentConfiguration(attachment, element);
157
+ this.attachmentConfigurations.set(attachment, configuration);
158
+ return configuration;
159
+ }
160
+ getCardAttachmentConfiguration(attachment) {
161
+ const existingConfiguration = this.attachmentConfigurations.get(attachment);
162
+ if (existingConfiguration) {
163
+ return existingConfiguration;
164
+ }
165
+ if (attachment.type === 'giphy') {
166
+ return this.attachmentConfigurationService.getGiphyAttachmentConfiguration(attachment);
167
+ }
168
+ else {
169
+ const configuration = this.attachmentConfigurationService.getScrapedImageAttachmentConfiguration(attachment);
170
+ this.attachmentConfigurations.set(attachment, configuration);
171
+ return configuration;
172
+ }
173
+ }
174
+ get isImageModalPrevButtonVisible() {
175
+ return this.imagesToViewCurrentIndex !== 0;
176
+ }
177
+ get isImageModalNextButtonVisible() {
178
+ return this.imagesToViewCurrentIndex !== this.imagesToView.length - 1;
179
+ }
180
+ createGallery(images) {
181
+ return [
182
+ {
183
+ type: 'gallery',
184
+ images,
185
+ },
186
+ ];
187
+ }
188
+ closeImageModal() {
189
+ this.imageModalStateChange.next('closed');
190
+ this.imagesToView = [];
191
+ }
192
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.0", ngImport: i0, type: AttachmentListComponent, deps: [{ token: i1.CustomTemplatesService }, { token: i2.ChannelService }, { token: i3.AttachmentConfigurationService }, { token: i4.MessageService }], target: i0.ɵɵFactoryTarget.Component }); }
193
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.0.0", type: AttachmentListComponent, selector: "stream-attachment-list", inputs: { messageId: "messageId", parentMessageId: "parentMessageId", attachments: "attachments" }, outputs: { imageModalStateChange: "imageModalStateChange" }, host: { properties: { "class": "this.class" } }, viewQueries: [{ propertyName: "modalContent", first: true, predicate: ["modalContent"], descendants: true, static: true }], usesOnChanges: true, ngImport: i0, template: "@if (\n orderedAttachments.length > 0 ||\n (customAttachments.length > 0 && customAttachmentsTemplate)\n) {\n <div class=\"str-chat__attachment-list\">\n @for (\n attachment of orderedAttachments;\n track attachment.image_url ||\n attachment.img_url ||\n attachment.asset_url ||\n attachment.thumb_url\n ) {\n <div\n data-testclass=\"attachment-container\"\n class=\"str-chat__message-attachment str-chat__message-attachment--{{\n attachment.type\n }} str-chat__message-attachment-dynamic-size\"\n [class.str-chat__message-attachment--card]=\"isCard(attachment)\"\n [class.str-chat-angular__message-attachment-file-single]=\"\n isFile(attachment)\n \"\n [class.str-chat__message-attachment--voice-recording]=\"\n isVoiceMessage(attachment)\n \"\n [class.str-chat__message-attachment-with-actions]=\"\n attachment.actions && attachment.actions.length > 0\n \"\n [class.str-chat__message-attachment--svg-image]=\"isSvg(attachment)\"\n >\n @if (isImage(attachment)) {\n <ng-container\n *ngTemplateOutlet=\"\n (customTemplatesService.imageAttachmentTemplate$ | async) ||\n defaultImage;\n context: getAttachmentContext(attachment)\n \"\n />\n <ng-template #defaultImage let-attachmentContext=\"attachment\">\n <img\n #imgElement\n class=\"str-chat__message-attachment--img\"\n data-testclass=\"image\"\n [src]=\"\n getImageAttachmentConfiguration(\n attachmentContext,\n 'single',\n imgElement\n ).url\n \"\n [alt]=\"attachmentContext?.fallback\"\n [ngStyle]=\"{\n height: getImageAttachmentConfiguration(\n attachmentContext,\n 'single',\n imgElement\n ).height,\n width: getImageAttachmentConfiguration(\n attachmentContext,\n 'single',\n imgElement\n ).width,\n '--original-height': getImageAttachmentConfiguration(\n attachmentContext,\n 'single',\n imgElement\n ).originalHeight,\n '--original-width': getImageAttachmentConfiguration(\n attachmentContext,\n 'single',\n imgElement\n ).originalWidth,\n }\"\n (click)=\"openImageModal([attachmentContext])\"\n (keyup.enter)=\"openImageModal([attachmentContext])\"\n />\n </ng-template>\n }\n @if (isGallery(attachment)) {\n <ng-container\n *ngTemplateOutlet=\"\n (customTemplatesService.galleryAttachmentTemplate$ | async) ||\n defaultGallery;\n context: getAttachmentContext(attachment)\n \"\n />\n <ng-template #defaultGallery let-attachmentContext=\"attachment\">\n <div\n class=\"str-chat__gallery\"\n data-testid=\"image-gallery\"\n [class.str-chat__gallery--square]=\"\n (attachmentContext?.images)!.length > 3\n \"\n [class.str-chat__gallery-two-rows]=\"\n (attachmentContext?.images)!.length > 2\n \"\n >\n @for (\n galleryImage of attachmentContext.images;\n track galleryImage.image_url ||\n galleryImage.img_url ||\n galleryImage.thumb_url;\n let index = $index;\n let isLast = $last\n ) {\n @if (index < 3 || (index === 3 && isLast)) {\n <button\n class=\"str-chat__gallery-image\"\n data-testclass=\"gallery-image\"\n [class.str-chat__message-attachment--svg-image]=\"\n isSvg(galleryImage)\n \"\n (click)=\"openImageModal(attachmentContext.images!, index)\"\n (keyup.enter)=\"\n openImageModal(attachmentContext.images!, index)\n \"\n >\n <img\n #imgElement\n fetchpriority=\"low\"\n loading=\"lazy\"\n [src]=\"\n getImageAttachmentConfiguration(\n galleryImage,\n 'gallery',\n imgElement\n ).url\n \"\n [alt]=\"galleryImage.fallback\"\n [style.--original-height]=\"\n getImageAttachmentConfiguration(\n galleryImage,\n 'gallery',\n imgElement\n ).originalHeight\n \"\n [style.--original-width]=\"\n getImageAttachmentConfiguration(\n galleryImage,\n 'gallery',\n imgElement\n ).originalWidth\n \"\n [ngStyle]=\"{\n height: getImageAttachmentConfiguration(\n galleryImage,\n 'gallery',\n imgElement\n ).height,\n width: getImageAttachmentConfiguration(\n galleryImage,\n 'gallery',\n imgElement\n ).width,\n }\"\n />\n </button>\n }\n @if (index === 3 && !isLast) {\n <button\n #element\n class=\"str-chat__gallery-placeholder\"\n data-testclass=\"gallery-image\"\n data-testid=\"more-image-button\"\n [class.str-chat__message-attachment--svg-image]=\"\n isSvg(galleryImage)\n \"\n [ngStyle]=\"{\n 'background-image':\n 'url(' +\n getImageAttachmentConfiguration(\n galleryImage,\n 'gallery',\n element\n ).url +\n ')',\n height: getImageAttachmentConfiguration(\n galleryImage,\n 'gallery',\n element\n ).height,\n width: getImageAttachmentConfiguration(\n galleryImage,\n 'gallery',\n element\n ).width,\n '--original-height': getImageAttachmentConfiguration(\n galleryImage,\n 'gallery',\n element\n ).originalHeight,\n '--original-width': getImageAttachmentConfiguration(\n galleryImage,\n 'gallery',\n element\n ).originalWidth,\n }\"\n (click)=\"openImageModal(attachmentContext.images!, index)\"\n (keyup.enter)=\"\n openImageModal(attachmentContext.images!, index)\n \"\n >\n <p\n [innerHTML]=\"\n 'streamChat.{{ imageCount }} more'\n | translate\n : {\n imageCount:\n attachmentContext!.images!.length - 4,\n }\n \"\n ></p>\n </button>\n }\n }\n </div>\n </ng-template>\n }\n @if (isVideo(attachment)) {\n <ng-container\n *ngTemplateOutlet=\"\n (customTemplatesService.videoAttachmentTemplate$ | async) ||\n defaultVideo;\n context: getAttachmentContext(attachment)\n \"\n />\n <ng-template #defaultVideo let-attachmentContext=\"attachment\">\n <div\n class=\"str-chat__player-wrapper\"\n data-testclass=\"video-attachment-parent\"\n [style.--original-height]=\"\n getVideoAttachmentConfiguration(attachmentContext, videoElement)\n .originalHeight\n \"\n [style.--original-width]=\"\n getVideoAttachmentConfiguration(attachmentContext, videoElement)\n .originalWidth\n \"\n [ngStyle]=\"{\n height: getVideoAttachmentConfiguration(\n attachmentContext,\n videoElement\n ).height,\n width: getVideoAttachmentConfiguration(\n attachmentContext,\n videoElement\n ).width,\n }\"\n >\n <video\n #videoElement\n class=\"str-chat__video-angular\"\n controls\n data-testclass=\"video-attachment\"\n [src]=\"\n getVideoAttachmentConfiguration(\n attachmentContext,\n videoElement\n ).url\n \"\n [poster]=\"\n getVideoAttachmentConfiguration(\n attachmentContext,\n videoElement\n ).thumbUrl\n \"\n ></video>\n </div>\n </ng-template>\n }\n @if (isFile(attachment)) {\n <ng-container\n *ngTemplateOutlet=\"\n (customTemplatesService.fileAttachmentTemplate$ | async) ||\n defaultFile;\n context: getAttachmentContext(attachment)\n \"\n />\n <ng-template #defaultFile let-attachmentContext=\"attachment\">\n <div\n class=\"str-chat__message-attachment-file--item str-chat-angular__message-attachment-file-single\"\n >\n <stream-icon-placeholder\n class=\"str-chat__attachment-type-icon\"\n icon=\"unspecified-filetype\"\n />\n <div class=\"str-chat__message-attachment-file--item-text\">\n <a\n class=\"str-chat__message-attachment-file--item-first-row\"\n data-testclass=\"file-link\"\n target=\"_blank\"\n href=\"{{ attachmentContext.asset_url }}\"\n >\n <div\n data-testclass=\"file-title\"\n class=\"str-chat__message-attachment-file--item-name\"\n >\n {{ attachmentContext.title }}\n </div>\n <stream-icon-placeholder\n class=\"str-chat__message-attachment-download-icon\"\n icon=\"download\"\n />\n </a>\n @if (hasFileSize(attachmentContext)) {\n <span\n class=\"str-chat__message-attachment-file--item-size\"\n data-testclass=\"size\"\n >{{ getFileSize(attachmentContext) }}</span\n >\n }\n </div>\n </div>\n </ng-template>\n }\n @if (isVoiceMessage(attachment)) {\n <ng-container\n *ngTemplateOutlet=\"\n (customTemplatesService.voiceRecordingAttachmentTemplate$\n | async) || defaultRecording;\n context: getAttachmentContext(attachment)\n \"\n />\n <ng-template #defaultRecording>\n <stream-voice-recording\n data-testclass=\"voice-recording\"\n [attachment]=\"attachment\"\n />\n </ng-template>\n }\n @if (\n isCard(attachment) && getCardAttachmentConfiguration(attachment);\n as attachmentConfiguration\n ) {\n <ng-container\n *ngTemplateOutlet=\"\n (customTemplatesService.cardAttachmentTemplate$ | async) ||\n defaultCard;\n context: getAttachmentContext(attachment)\n \"\n />\n <ng-template #defaultCard let-attachmentContext=\"attachment\">\n <div\n class=\"str-chat__message-attachment-card str-chat__message-attachment-card--{{\n attachmentContext.type\n }}\"\n >\n @if (attachmentConfiguration.url) {\n <div class=\"str-chat__message-attachment-card--header\">\n @if (attachmentContext.type === \"video\") {\n <a\n [href]=\"\n attachmentContext.title_link ||\n attachmentContext.og_scrape_url\n \"\n target=\"_blank\"\n data-testclass=\"scraped-video\"\n >\n <ng-content *ngTemplateOutlet=\"cardImage\" />\n <div\n class=\"str-chat__message-attachment-card--video-play\"\n ></div>\n <stream-icon-placeholder icon=\"play\" />\n </a>\n } @else {\n <ng-content *ngTemplateOutlet=\"cardImage\" />\n }\n <ng-template #cardImage\n ><img\n fetchpriority=\"low\"\n loading=\"lazy\"\n data-testclass=\"card-img\"\n alt=\"{{ attachmentConfiguration.url }}\"\n [src]=\"attachmentConfiguration.url\"\n [ngStyle]=\"{\n height: attachmentConfiguration.height,\n width: attachmentConfiguration.width,\n }\"\n /></ng-template>\n </div>\n }\n\n <div class=\"str-chat__message-attachment-card--content\">\n <div class=\"str-chat__message-attachment-card--flex\">\n @if (attachmentContext.title) {\n <div\n data-testclass=\"card-title\"\n class=\"str-chat__message-attachment-card--title\"\n >\n {{ attachmentContext.title }}\n </div>\n }\n @if (attachmentContext.text) {\n <div\n class=\"str-chat__message-attachment-card--text\"\n data-testclass=\"card-text\"\n >\n {{ attachmentContext.text }}\n </div>\n }\n @if (\n attachmentContext.title_link ||\n attachmentContext.og_scrape_url\n ) {\n <a\n class=\"str-chat__message-attachment-card--url\"\n data-testclass=\"url-link\"\n noopener\n noreferrer\n target=\"_blank\"\n href=\"{{\n attachmentContext.title_link ||\n attachmentContext.og_scrape_url\n }}\"\n >\n {{\n trimUrl(\n attachmentContext.title_link ||\n attachmentContext.og_scrape_url\n )\n }}\n </a>\n }\n </div>\n </div>\n </div>\n </ng-template>\n }\n @if (attachment.actions && attachment.actions.length > 0) {\n <ng-container\n *ngTemplateOutlet=\"\n (customTemplatesService.attachmentActionsTemplate$ | async) ||\n defaultActions;\n context: getAttachmentContext(attachment)\n \"\n />\n <ng-template #defaultActions let-attachmentContext=\"attachment\">\n <div class=\"str-chat__message-attachment-actions\">\n <div class=\"str-chat__message-attachment-actions-form\">\n @for (action of attachmentContext.actions; track action.value) {\n <button\n data-testclass=\"attachment-action\"\n class=\"str-chat__message-attachment-actions-button str-chat__message-attachment-actions-button--{{\n action.style\n }}\"\n (click)=\"sendAction(action)\"\n (keyup.enter)=\"sendAction(action)\"\n >\n {{ action.text }}\n </button>\n }\n </div>\n </div>\n </ng-template>\n }\n </div>\n }\n @if (customAttachmentsTemplate) {\n <ng-template\n *ngTemplateOutlet=\"\n customAttachmentsTemplate;\n context: {\n messageId: messageId!,\n parentMessageId: parentMessageId,\n attachments: customAttachments,\n }\n \"\n />\n }\n\n @if (imagesToView && imagesToView.length > 0) {\n <ng-container\n *ngTemplateOutlet=\"\n (customTemplatesService.modalTemplate$ | async) || defaultModal;\n context: getModalContext()\n \"\n />\n }\n </div>\n}\n\n<ng-template\n #defaultModal\n let-isOpen=\"isOpen\"\n let-isOpenChangeHandler=\"isOpenChangeHandler\"\n let-content=\"content\"\n>\n <stream-modal\n class=\"stream-chat-angular__image-modal-host\"\n [isOpen]=\"isOpen\"\n [content]=\"content\"\n (isOpenChange)=\"isOpenChangeHandler($event)\"\n />\n</ng-template>\n\n<ng-template #modalContent>\n <div class=\"stream-chat-angular__image-modal str-chat__image-carousel\">\n <img\n #imgElement\n class=\"stream-chat-angular__image-modal-image str-chat__image-carousel-image\"\n data-testid=\"modal-image\"\n [src]=\"\n getCarouselImageAttachmentConfiguration(\n imagesToView[imagesToViewCurrentIndex],\n imgElement\n ).url\n \"\n [style.--original-height]=\"\n getCarouselImageAttachmentConfiguration(\n imagesToView[imagesToViewCurrentIndex],\n imgElement\n ).originalHeight\n \"\n [style.--original-width]=\"\n getCarouselImageAttachmentConfiguration(\n imagesToView[imagesToViewCurrentIndex],\n imgElement\n ).originalWidth\n \"\n [alt]=\"imagesToView[imagesToViewCurrentIndex].fallback\"\n [ngStyle]=\"{\n width: getCarouselImageAttachmentConfiguration(\n imagesToView[imagesToViewCurrentIndex],\n imgElement\n ).width,\n height: getCarouselImageAttachmentConfiguration(\n imagesToView[imagesToViewCurrentIndex],\n imgElement\n ).height,\n }\"\n />\n <div>\n <button\n class=\"stream-chat-angular__image-modal-stepper str-chat__image-carousel-stepper str-chat__image-carousel-stepper-prev\"\n data-testid=\"image-modal-prev\"\n type=\"button\"\n [ngStyle]=\"{\n visibility: isImageModalPrevButtonVisible ? 'visible' : 'hidden',\n }\"\n (click)=\"stepImages(-1)\"\n (keyup.enter)=\"stepImages(-1)\"\n >\n <stream-icon-placeholder icon=\"arrow-left\" />\n </button>\n <button\n class=\"stream-chat-angular__image-modal-stepper str-chat__image-carousel-stepper str-chat__image-carousel-stepper-next\"\n type=\"button\"\n data-testid=\"image-modal-next\"\n [ngStyle]=\"{\n visibility: isImageModalNextButtonVisible ? 'visible' : 'hidden',\n }\"\n (click)=\"stepImages(1)\"\n (keyup.enter)=\"stepImages(1)\"\n >\n <stream-icon-placeholder icon=\"arrow-right\" />\n </button>\n </div>\n </div>\n</ng-template>\n", dependencies: [{ kind: "directive", type: i5.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i5.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "component", type: i6.VoiceRecordingComponent, selector: "stream-voice-recording", inputs: ["attachment"] }, { kind: "component", type: i7.IconPlaceholderComponent, selector: "stream-icon-placeholder", inputs: ["icon"] }, { kind: "component", type: i8.ModalComponent, selector: "stream-modal", inputs: ["isOpen", "content"], outputs: ["isOpenChange"] }, { kind: "pipe", type: i5.AsyncPipe, name: "async" }, { kind: "pipe", type: i9.TranslatePipe, name: "translate" }] }); }
194
+ }
195
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0", ngImport: i0, type: AttachmentListComponent, decorators: [{
196
+ type: Component,
197
+ args: [{ selector: 'stream-attachment-list', template: "@if (\n orderedAttachments.length > 0 ||\n (customAttachments.length > 0 && customAttachmentsTemplate)\n) {\n <div class=\"str-chat__attachment-list\">\n @for (\n attachment of orderedAttachments;\n track attachment.image_url ||\n attachment.img_url ||\n attachment.asset_url ||\n attachment.thumb_url\n ) {\n <div\n data-testclass=\"attachment-container\"\n class=\"str-chat__message-attachment str-chat__message-attachment--{{\n attachment.type\n }} str-chat__message-attachment-dynamic-size\"\n [class.str-chat__message-attachment--card]=\"isCard(attachment)\"\n [class.str-chat-angular__message-attachment-file-single]=\"\n isFile(attachment)\n \"\n [class.str-chat__message-attachment--voice-recording]=\"\n isVoiceMessage(attachment)\n \"\n [class.str-chat__message-attachment-with-actions]=\"\n attachment.actions && attachment.actions.length > 0\n \"\n [class.str-chat__message-attachment--svg-image]=\"isSvg(attachment)\"\n >\n @if (isImage(attachment)) {\n <ng-container\n *ngTemplateOutlet=\"\n (customTemplatesService.imageAttachmentTemplate$ | async) ||\n defaultImage;\n context: getAttachmentContext(attachment)\n \"\n />\n <ng-template #defaultImage let-attachmentContext=\"attachment\">\n <img\n #imgElement\n class=\"str-chat__message-attachment--img\"\n data-testclass=\"image\"\n [src]=\"\n getImageAttachmentConfiguration(\n attachmentContext,\n 'single',\n imgElement\n ).url\n \"\n [alt]=\"attachmentContext?.fallback\"\n [ngStyle]=\"{\n height: getImageAttachmentConfiguration(\n attachmentContext,\n 'single',\n imgElement\n ).height,\n width: getImageAttachmentConfiguration(\n attachmentContext,\n 'single',\n imgElement\n ).width,\n '--original-height': getImageAttachmentConfiguration(\n attachmentContext,\n 'single',\n imgElement\n ).originalHeight,\n '--original-width': getImageAttachmentConfiguration(\n attachmentContext,\n 'single',\n imgElement\n ).originalWidth,\n }\"\n (click)=\"openImageModal([attachmentContext])\"\n (keyup.enter)=\"openImageModal([attachmentContext])\"\n />\n </ng-template>\n }\n @if (isGallery(attachment)) {\n <ng-container\n *ngTemplateOutlet=\"\n (customTemplatesService.galleryAttachmentTemplate$ | async) ||\n defaultGallery;\n context: getAttachmentContext(attachment)\n \"\n />\n <ng-template #defaultGallery let-attachmentContext=\"attachment\">\n <div\n class=\"str-chat__gallery\"\n data-testid=\"image-gallery\"\n [class.str-chat__gallery--square]=\"\n (attachmentContext?.images)!.length > 3\n \"\n [class.str-chat__gallery-two-rows]=\"\n (attachmentContext?.images)!.length > 2\n \"\n >\n @for (\n galleryImage of attachmentContext.images;\n track galleryImage.image_url ||\n galleryImage.img_url ||\n galleryImage.thumb_url;\n let index = $index;\n let isLast = $last\n ) {\n @if (index < 3 || (index === 3 && isLast)) {\n <button\n class=\"str-chat__gallery-image\"\n data-testclass=\"gallery-image\"\n [class.str-chat__message-attachment--svg-image]=\"\n isSvg(galleryImage)\n \"\n (click)=\"openImageModal(attachmentContext.images!, index)\"\n (keyup.enter)=\"\n openImageModal(attachmentContext.images!, index)\n \"\n >\n <img\n #imgElement\n fetchpriority=\"low\"\n loading=\"lazy\"\n [src]=\"\n getImageAttachmentConfiguration(\n galleryImage,\n 'gallery',\n imgElement\n ).url\n \"\n [alt]=\"galleryImage.fallback\"\n [style.--original-height]=\"\n getImageAttachmentConfiguration(\n galleryImage,\n 'gallery',\n imgElement\n ).originalHeight\n \"\n [style.--original-width]=\"\n getImageAttachmentConfiguration(\n galleryImage,\n 'gallery',\n imgElement\n ).originalWidth\n \"\n [ngStyle]=\"{\n height: getImageAttachmentConfiguration(\n galleryImage,\n 'gallery',\n imgElement\n ).height,\n width: getImageAttachmentConfiguration(\n galleryImage,\n 'gallery',\n imgElement\n ).width,\n }\"\n />\n </button>\n }\n @if (index === 3 && !isLast) {\n <button\n #element\n class=\"str-chat__gallery-placeholder\"\n data-testclass=\"gallery-image\"\n data-testid=\"more-image-button\"\n [class.str-chat__message-attachment--svg-image]=\"\n isSvg(galleryImage)\n \"\n [ngStyle]=\"{\n 'background-image':\n 'url(' +\n getImageAttachmentConfiguration(\n galleryImage,\n 'gallery',\n element\n ).url +\n ')',\n height: getImageAttachmentConfiguration(\n galleryImage,\n 'gallery',\n element\n ).height,\n width: getImageAttachmentConfiguration(\n galleryImage,\n 'gallery',\n element\n ).width,\n '--original-height': getImageAttachmentConfiguration(\n galleryImage,\n 'gallery',\n element\n ).originalHeight,\n '--original-width': getImageAttachmentConfiguration(\n galleryImage,\n 'gallery',\n element\n ).originalWidth,\n }\"\n (click)=\"openImageModal(attachmentContext.images!, index)\"\n (keyup.enter)=\"\n openImageModal(attachmentContext.images!, index)\n \"\n >\n <p\n [innerHTML]=\"\n 'streamChat.{{ imageCount }} more'\n | translate\n : {\n imageCount:\n attachmentContext!.images!.length - 4,\n }\n \"\n ></p>\n </button>\n }\n }\n </div>\n </ng-template>\n }\n @if (isVideo(attachment)) {\n <ng-container\n *ngTemplateOutlet=\"\n (customTemplatesService.videoAttachmentTemplate$ | async) ||\n defaultVideo;\n context: getAttachmentContext(attachment)\n \"\n />\n <ng-template #defaultVideo let-attachmentContext=\"attachment\">\n <div\n class=\"str-chat__player-wrapper\"\n data-testclass=\"video-attachment-parent\"\n [style.--original-height]=\"\n getVideoAttachmentConfiguration(attachmentContext, videoElement)\n .originalHeight\n \"\n [style.--original-width]=\"\n getVideoAttachmentConfiguration(attachmentContext, videoElement)\n .originalWidth\n \"\n [ngStyle]=\"{\n height: getVideoAttachmentConfiguration(\n attachmentContext,\n videoElement\n ).height,\n width: getVideoAttachmentConfiguration(\n attachmentContext,\n videoElement\n ).width,\n }\"\n >\n <video\n #videoElement\n class=\"str-chat__video-angular\"\n controls\n data-testclass=\"video-attachment\"\n [src]=\"\n getVideoAttachmentConfiguration(\n attachmentContext,\n videoElement\n ).url\n \"\n [poster]=\"\n getVideoAttachmentConfiguration(\n attachmentContext,\n videoElement\n ).thumbUrl\n \"\n ></video>\n </div>\n </ng-template>\n }\n @if (isFile(attachment)) {\n <ng-container\n *ngTemplateOutlet=\"\n (customTemplatesService.fileAttachmentTemplate$ | async) ||\n defaultFile;\n context: getAttachmentContext(attachment)\n \"\n />\n <ng-template #defaultFile let-attachmentContext=\"attachment\">\n <div\n class=\"str-chat__message-attachment-file--item str-chat-angular__message-attachment-file-single\"\n >\n <stream-icon-placeholder\n class=\"str-chat__attachment-type-icon\"\n icon=\"unspecified-filetype\"\n />\n <div class=\"str-chat__message-attachment-file--item-text\">\n <a\n class=\"str-chat__message-attachment-file--item-first-row\"\n data-testclass=\"file-link\"\n target=\"_blank\"\n href=\"{{ attachmentContext.asset_url }}\"\n >\n <div\n data-testclass=\"file-title\"\n class=\"str-chat__message-attachment-file--item-name\"\n >\n {{ attachmentContext.title }}\n </div>\n <stream-icon-placeholder\n class=\"str-chat__message-attachment-download-icon\"\n icon=\"download\"\n />\n </a>\n @if (hasFileSize(attachmentContext)) {\n <span\n class=\"str-chat__message-attachment-file--item-size\"\n data-testclass=\"size\"\n >{{ getFileSize(attachmentContext) }}</span\n >\n }\n </div>\n </div>\n </ng-template>\n }\n @if (isVoiceMessage(attachment)) {\n <ng-container\n *ngTemplateOutlet=\"\n (customTemplatesService.voiceRecordingAttachmentTemplate$\n | async) || defaultRecording;\n context: getAttachmentContext(attachment)\n \"\n />\n <ng-template #defaultRecording>\n <stream-voice-recording\n data-testclass=\"voice-recording\"\n [attachment]=\"attachment\"\n />\n </ng-template>\n }\n @if (\n isCard(attachment) && getCardAttachmentConfiguration(attachment);\n as attachmentConfiguration\n ) {\n <ng-container\n *ngTemplateOutlet=\"\n (customTemplatesService.cardAttachmentTemplate$ | async) ||\n defaultCard;\n context: getAttachmentContext(attachment)\n \"\n />\n <ng-template #defaultCard let-attachmentContext=\"attachment\">\n <div\n class=\"str-chat__message-attachment-card str-chat__message-attachment-card--{{\n attachmentContext.type\n }}\"\n >\n @if (attachmentConfiguration.url) {\n <div class=\"str-chat__message-attachment-card--header\">\n @if (attachmentContext.type === \"video\") {\n <a\n [href]=\"\n attachmentContext.title_link ||\n attachmentContext.og_scrape_url\n \"\n target=\"_blank\"\n data-testclass=\"scraped-video\"\n >\n <ng-content *ngTemplateOutlet=\"cardImage\" />\n <div\n class=\"str-chat__message-attachment-card--video-play\"\n ></div>\n <stream-icon-placeholder icon=\"play\" />\n </a>\n } @else {\n <ng-content *ngTemplateOutlet=\"cardImage\" />\n }\n <ng-template #cardImage\n ><img\n fetchpriority=\"low\"\n loading=\"lazy\"\n data-testclass=\"card-img\"\n alt=\"{{ attachmentConfiguration.url }}\"\n [src]=\"attachmentConfiguration.url\"\n [ngStyle]=\"{\n height: attachmentConfiguration.height,\n width: attachmentConfiguration.width,\n }\"\n /></ng-template>\n </div>\n }\n\n <div class=\"str-chat__message-attachment-card--content\">\n <div class=\"str-chat__message-attachment-card--flex\">\n @if (attachmentContext.title) {\n <div\n data-testclass=\"card-title\"\n class=\"str-chat__message-attachment-card--title\"\n >\n {{ attachmentContext.title }}\n </div>\n }\n @if (attachmentContext.text) {\n <div\n class=\"str-chat__message-attachment-card--text\"\n data-testclass=\"card-text\"\n >\n {{ attachmentContext.text }}\n </div>\n }\n @if (\n attachmentContext.title_link ||\n attachmentContext.og_scrape_url\n ) {\n <a\n class=\"str-chat__message-attachment-card--url\"\n data-testclass=\"url-link\"\n noopener\n noreferrer\n target=\"_blank\"\n href=\"{{\n attachmentContext.title_link ||\n attachmentContext.og_scrape_url\n }}\"\n >\n {{\n trimUrl(\n attachmentContext.title_link ||\n attachmentContext.og_scrape_url\n )\n }}\n </a>\n }\n </div>\n </div>\n </div>\n </ng-template>\n }\n @if (attachment.actions && attachment.actions.length > 0) {\n <ng-container\n *ngTemplateOutlet=\"\n (customTemplatesService.attachmentActionsTemplate$ | async) ||\n defaultActions;\n context: getAttachmentContext(attachment)\n \"\n />\n <ng-template #defaultActions let-attachmentContext=\"attachment\">\n <div class=\"str-chat__message-attachment-actions\">\n <div class=\"str-chat__message-attachment-actions-form\">\n @for (action of attachmentContext.actions; track action.value) {\n <button\n data-testclass=\"attachment-action\"\n class=\"str-chat__message-attachment-actions-button str-chat__message-attachment-actions-button--{{\n action.style\n }}\"\n (click)=\"sendAction(action)\"\n (keyup.enter)=\"sendAction(action)\"\n >\n {{ action.text }}\n </button>\n }\n </div>\n </div>\n </ng-template>\n }\n </div>\n }\n @if (customAttachmentsTemplate) {\n <ng-template\n *ngTemplateOutlet=\"\n customAttachmentsTemplate;\n context: {\n messageId: messageId!,\n parentMessageId: parentMessageId,\n attachments: customAttachments,\n }\n \"\n />\n }\n\n @if (imagesToView && imagesToView.length > 0) {\n <ng-container\n *ngTemplateOutlet=\"\n (customTemplatesService.modalTemplate$ | async) || defaultModal;\n context: getModalContext()\n \"\n />\n }\n </div>\n}\n\n<ng-template\n #defaultModal\n let-isOpen=\"isOpen\"\n let-isOpenChangeHandler=\"isOpenChangeHandler\"\n let-content=\"content\"\n>\n <stream-modal\n class=\"stream-chat-angular__image-modal-host\"\n [isOpen]=\"isOpen\"\n [content]=\"content\"\n (isOpenChange)=\"isOpenChangeHandler($event)\"\n />\n</ng-template>\n\n<ng-template #modalContent>\n <div class=\"stream-chat-angular__image-modal str-chat__image-carousel\">\n <img\n #imgElement\n class=\"stream-chat-angular__image-modal-image str-chat__image-carousel-image\"\n data-testid=\"modal-image\"\n [src]=\"\n getCarouselImageAttachmentConfiguration(\n imagesToView[imagesToViewCurrentIndex],\n imgElement\n ).url\n \"\n [style.--original-height]=\"\n getCarouselImageAttachmentConfiguration(\n imagesToView[imagesToViewCurrentIndex],\n imgElement\n ).originalHeight\n \"\n [style.--original-width]=\"\n getCarouselImageAttachmentConfiguration(\n imagesToView[imagesToViewCurrentIndex],\n imgElement\n ).originalWidth\n \"\n [alt]=\"imagesToView[imagesToViewCurrentIndex].fallback\"\n [ngStyle]=\"{\n width: getCarouselImageAttachmentConfiguration(\n imagesToView[imagesToViewCurrentIndex],\n imgElement\n ).width,\n height: getCarouselImageAttachmentConfiguration(\n imagesToView[imagesToViewCurrentIndex],\n imgElement\n ).height,\n }\"\n />\n <div>\n <button\n class=\"stream-chat-angular__image-modal-stepper str-chat__image-carousel-stepper str-chat__image-carousel-stepper-prev\"\n data-testid=\"image-modal-prev\"\n type=\"button\"\n [ngStyle]=\"{\n visibility: isImageModalPrevButtonVisible ? 'visible' : 'hidden',\n }\"\n (click)=\"stepImages(-1)\"\n (keyup.enter)=\"stepImages(-1)\"\n >\n <stream-icon-placeholder icon=\"arrow-left\" />\n </button>\n <button\n class=\"stream-chat-angular__image-modal-stepper str-chat__image-carousel-stepper str-chat__image-carousel-stepper-next\"\n type=\"button\"\n data-testid=\"image-modal-next\"\n [ngStyle]=\"{\n visibility: isImageModalNextButtonVisible ? 'visible' : 'hidden',\n }\"\n (click)=\"stepImages(1)\"\n (keyup.enter)=\"stepImages(1)\"\n >\n <stream-icon-placeholder icon=\"arrow-right\" />\n </button>\n </div>\n </div>\n</ng-template>\n" }]
198
+ }], ctorParameters: () => [{ type: i1.CustomTemplatesService }, { type: i2.ChannelService }, { type: i3.AttachmentConfigurationService }, { type: i4.MessageService }], propDecorators: { messageId: [{
199
+ type: Input
200
+ }], parentMessageId: [{
201
+ type: Input
202
+ }], attachments: [{
203
+ type: Input
204
+ }], imageModalStateChange: [{
205
+ type: Output
206
+ }], class: [{
207
+ type: HostBinding
208
+ }], modalContent: [{
209
+ type: ViewChild,
210
+ args: ['modalContent', { static: true }]
211
+ }] } });
212
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXR0YWNobWVudC1saXN0LmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL3N0cmVhbS1jaGF0LWFuZ3VsYXIvc3JjL2xpYi9hdHRhY2htZW50LWxpc3QvYXR0YWNobWVudC1saXN0LmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL3N0cmVhbS1jaGF0LWFuZ3VsYXIvc3JjL2xpYi9hdHRhY2htZW50LWxpc3QvYXR0YWNobWVudC1saXN0LmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFDTCxTQUFTLEVBQ1QsWUFBWSxFQUNaLFdBQVcsRUFDWCxLQUFLLEVBSUwsTUFBTSxFQUdOLFNBQVMsR0FDVixNQUFNLGVBQWUsQ0FBQztBQVd2QixPQUFPLFdBQVcsTUFBTSxjQUFjLENBQUM7QUFDdkMsT0FBTyxFQUFFLGlCQUFpQixFQUFFLE1BQU0sd0JBQXdCLENBQUM7Ozs7Ozs7Ozs7O0FBTzNEOztHQUVHO0FBTUgsTUFBTSxPQUFPLHVCQUF1QjtJQW1DbEMsWUFDa0Isc0JBQThDLEVBQ3RELGNBQThCLEVBQzlCLDhCQUE4RCxFQUM5RCxjQUE4QjtRQUh0QiwyQkFBc0IsR0FBdEIsc0JBQXNCLENBQXdCO1FBQ3RELG1CQUFjLEdBQWQsY0FBYyxDQUFnQjtRQUM5QixtQ0FBOEIsR0FBOUIsOEJBQThCLENBQWdDO1FBQzlELG1CQUFjLEdBQWQsY0FBYyxDQUFnQjtRQTlCeEM7O1dBRUc7UUFDTSxnQkFBVyxHQUE0QyxFQUFFLENBQUM7UUFDbkU7O1dBRUc7UUFDZ0IsMEJBQXFCLEdBQUcsSUFBSSxZQUFZLEVBRXhELENBQUM7UUFDVyxVQUFLLEdBQUcsd0NBQXdDLENBQUM7UUFDaEUsdUJBQWtCLEdBQTRDLEVBQUUsQ0FBQztRQUNqRSxzQkFBaUIsR0FBNEMsRUFBRSxDQUFDO1FBQ2hFLGlCQUFZLEdBQTRDLEVBQUUsQ0FBQztRQUMzRCw2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O2dCQUlHLFdBQVc7c0JBQW5CLEtBQUs7Z0JBSWEscUJBQXFCO3NCQUF2QyxNQUFNO2dCQUdRLEtBQUs7c0JBQW5CLFdBQVc7Z0JBT0osWUFBWTtzQkFEbkIsU0FBUzt1QkFBQyxjQUFjLEVBQUUsRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcbiAgQ29tcG9uZW50LFxuICBFdmVudEVtaXR0ZXIsXG4gIEhvc3RCaW5kaW5nLFxuICBJbnB1dCxcbiAgT25DaGFuZ2VzLFxuICBPbkRlc3Ryb3ksXG4gIE9uSW5pdCxcbiAgT3V0cHV0LFxuICBTaW1wbGVDaGFuZ2VzLFxuICBUZW1wbGF0ZVJlZixcbiAgVmlld0NoaWxkLFxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IEFjdGlvbiwgQXR0YWNobWVudCB9IGZyb20gJ3N0cmVhbS1jaGF0JztcbmltcG9ydCB7XG4gIE1vZGFsQ29udGV4dCxcbiAgRGVmYXVsdFN0cmVhbUNoYXRHZW5lcmljcyxcbiAgQXR0YWNobWVudENvbmZpZ3JhdGlvbixcbiAgVmlkZW9BdHRhY2htZW50Q29uZmlndXJhdGlvbixcbiAgSW1hZ2VBdHRhY2htZW50Q29uZmlndXJhdGlvbixcbiAgQXR0YWNobWVudENvbnRleHQsXG4gIEN1c3RvbUF0dGFjaG1lbnRMaXN0Q29udGV4dCxcbn0gZnJvbSAnLi4vdHlwZXMnO1xuaW1wb3J0IHByZXR0eWJ5dGVzIGZyb20gJ3ByZXR0eS1ieXRlcyc7XG5pbXBvcnQgeyBpc0ltYWdlQXR0YWNobWVudCB9IGZyb20gJy4uL2lzLWltYWdlLWF0dGFjaG1lbnQnO1xuaW1wb3J0IHsgQ2hhbm5lbFNlcnZpY2UgfSBmcm9tICcuLi9jaGFubmVsLnNlcnZpY2UnO1xuaW1wb3J0IHsgQ3VzdG9tVGVtcGxhdGVzU2VydmljZSB9IGZyb20gJy4uL2N1c3RvbS10ZW1wbGF0ZXMuc2VydmljZSc7XG5pbXBvcnQgeyBBdHRhY2htZW50Q29uZmlndXJhdGlvblNlcnZpY2UgfSBmcm9tICcuLi9hdHRhY2htZW50LWNvbmZpZ3VyYXRpb24uc2VydmljZSc7XG5pbXBvcnQgeyBTdWJzY3JpcHRpb24gfSBmcm9tICdyeGpzJztcbmltcG9ydCB7IE1lc3NhZ2VTZXJ2aWNlIH0gZnJvbSAnLi4vbWVzc2FnZS5zZXJ2aWNlJztcblxuLyoqXG4gKiBUaGUgYEF0dGFjaG1lbnRMaXN0YCBjb21wb25lbnQgZGlzcGxheXMgdGhlIGF0dGFjaG1lbnRzIG9mIGEgbWVzc2FnZVxuICovXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICdzdHJlYW0tYXR0YWNobWVudC1saXN0JyxcbiAgdGVtcGxhdGVVcmw6ICcuL2F0dGFjaG1lbnQtbGlzdC5jb21wb25lbnQuaHRtbCcsXG4gIHN0eWxlczogW10sXG59KVxuZXhwb3J0IGNsYXNzIEF0dGFjaG1lbnRMaXN0Q29tcG9uZW50IGltcGxlbWVudHMgT25DaGFuZ2VzLCBPbkluaXQsIE9uRGVzdHJveSB7XG4gIC8qKlxuICAgKiBUaGUgaWQgb2YgdGhlIG1lc3NhZ2UgdGhlIGF0dGFjaG1lbnRzIGJlbG9uZyB0b1xuICAgKi9cbiAgQElucHV0KCkgbWVzc2FnZUlkOiBzdHJpbmcgfCB1bmRlZmluZWQ7XG4gIC8qKlxuICAgKiBUaGUgcGFyZW50IGlkIG9mIHRoZSBtZXNzYWdlIHRoZSBhdHRhY2htZW50cyBiZWxvbmcgdG9cbiAgICovXG4gIEBJbnB1dCgpIHBhcmVudE1lc3NhZ2VJZDogc3RyaW5nIHwgdW5kZWZpbmVkO1xuICAvKipcbiAgICogVGhlIGF0dGFjaG1lbnRzIHRvIGRpc3BsYXlcbiAgICovXG4gIEBJbnB1dCgpIGF0dGFjaG1lbnRzOiBBdHRhY2htZW50PERlZmF1bHRTdHJlYW1DaGF0R2VuZXJpY3M+W10gPSBbXTtcbiAgLyoqXG4gICAqIEVtaXRzIHRoZSBzdGF0ZSBvZiB0aGUgaW1hZ2UgY2Fyb3VzZWwgd2luZG93XG4gICAqL1xuICBAT3V0cHV0KCkgcmVhZG9ubHkgaW1hZ2VNb2RhbFN0YXRlQ2hhbmdlID0gbmV3IEV2ZW50RW1pdHRlcjxcbiAgICAnb3BlbmVkJyB8ICdjbG9zZWQnXG4gID4oKTtcbiAgQEhvc3RCaW5kaW5nKCkgY2xhc3MgPSAnc3RyLWNoYXRfX2F0dGFjaG1lbnQtbGlzdC1hbmd1bGFyLWhvc3QnO1xuICBvcmRlcmVkQXR0YWNobWVudHM6IEF0dGFjaG1lbnQ8RGVmYXVsdFN0cmVhbUNoYXRHZW5lcmljcz5bXSA9IFtdO1xuICBjdXN0b21BdHRhY2htZW50czogQXR0YWNobWVudDxEZWZhdWx0U3RyZWFtQ2hhdEdlbmVyaWNzPltdID0gW107XG4gIGltYWdlc1RvVmlldzogQXR0YWNobWVudDxEZWZhdWx0U3RyZWFtQ2hhdEdlbmVyaWNzPltdID0gW107XG4gIGltYWdlc1RvVmlld0N1cnJlbnRJbmRleCA9IDA7XG4gIGN1c3RvbUF0dGFjaG1lbnRzVGVtcGxhdGU/OiBUZW1wbGF0ZVJlZjxDdXN0b21BdHRhY2htZW50TGlzdENvbnRleHQ+O1xuICBAVmlld0NoaWxkKCdtb2RhbENvbnRlbnQnLCB7IHN0YXRpYzogdHJ1ZSB9KVxuICBwcml2YXRlIG1vZGFsQ29udGVudCE6IFRlbXBsYXRlUmVmPHZvaWQ+O1xuICBwcml2YXRlIGF0dGFjaG1lbnRDb25maWd1cmF0aW9uczogTWFwPFxuICAgIEF0dGFjaG1lbnQsXG4gICAgfCBBdHRhY2htZW50Q29uZmlncmF0aW9uXG4gICAgfCBWaWRlb0F0dGFjaG1lbnRDb25maWd1cmF0aW9uXG4gICAgfCBJbWFnZUF0dGFjaG1lbnRDb25maWd1cmF0aW9uXG4gID4gPSBuZXcgTWFwKCk7XG4gIHByaXZhdGUgc3Vic2NyaXB0aW9uczogU3Vic2NyaXB0aW9uW10gPSBbXTtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBwdWJsaWMgcmVhZG9ubHkgY3VzdG9tVGVtcGxhdGVzU2VydmljZTogQ3VzdG9tVGVtcGxhdGVzU2VydmljZSxcbiAgICBwcml2YXRlIGNoYW5uZWxTZXJ2aWNlOiBDaGFubmVsU2VydmljZSxcbiAgICBwcml2YXRlIGF0dGFjaG1lbnRDb25maWd1cmF0aW9uU2VydmljZTogQXR0YWNobWVudENvbmZpZ3VyYXRpb25TZXJ2aWNlLFxuICAgIHByaXZhdGUgbWVzc2FnZVNlcnZpY2U6IE1lc3NhZ2VTZXJ2aWNlLFxuICApIHt9XG5cbiAgbmdPbkNoYW5nZXMoY2hhbmdlczogU2ltcGxlQ2hhbmdlcyk6IHZvaWQge1xuICAgIGlmIChjaGFuZ2VzLmF0dGFjaG1lbnRzKSB7XG4gICAgICBjb25zdCBidWlsdEluQXR0YWNobWVudHM6IEF0dGFjaG1lbnRbXSA9IFtdO1xuICAgICAgY29uc3QgY3VzdG9tQXR0YWNobWVudHM6IEF0dGFjaG1lbnRbXSA9IFtdO1xuICAgICAgdGhpcy5hdHRhY2htZW50cy5mb3JFYWNoKChhKSA9PiB7XG4gICAgICAgIGlmICh0aGlzLm1lc3NhZ2VTZXJ2aWNlLmlzQ3VzdG9tQXR0YWNobWVudChhKSkge1xuICAgICAgICAgIGN1c3RvbUF0dGFjaG1lbnRzLnB1c2goYSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgYnVpbHRJbkF0dGFjaG1lbnRzLnB1c2goYSk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgICAgY29uc3QgaW1hZ2VzID0gYnVpbHRJbkF0dGFjaG1lbnRzLmZpbHRlcih0aGlzLmlzSW1hZ2UpO1xuICAgICAgY29uc3QgY29udGFpbnNHYWxsZXJ5ID0gaW1hZ2VzLmxlbmd0aCA+PSAyO1xuICAgICAgdGhpcy5vcmRlcmVkQXR0YWNobWVudHMgPSBbXG4gICAgICAgIC4uLihjb250YWluc0dhbGxlcnkgPyB0aGlzLmNyZWF0ZUdhbGxlcnkoaW1hZ2VzKSA6IGltYWdlcyksXG4gICAgICAgIC4uLmJ1aWx0SW5BdHRhY2htZW50cy5maWx0ZXIoKGEpID0+IHRoaXMuaXNWaWRlbyhhKSksXG4gICAgICAgIC4uLmJ1aWx0SW5BdHRhY2htZW50cy5maWx0ZXIoKGEpID0+IHRoaXMuaXNWb2ljZU1lc3NhZ2UoYSkpLFxuICAgICAgICAuLi5idWlsdEluQXR0YWNobWVudHMuZmlsdGVyKChhKSA9PiB0aGlzLmlzRmlsZShhKSksXG4gICAgICBdO1xuICAgICAgdGhpcy5hdHRhY2htZW50Q29uZmlndXJhdGlvbnMgPSBuZXcgTWFwKCk7XG4gICAgICAvLyBEaXNwbGF5IGxpbmsgYXR0YWNobWVudHMgb25seSBpZiB0aGVyZSBhcmUgbm8gb3RoZXIgYXR0YWNobWVudHNcbiAgICAgIC8vIEdpcGh5LXMgYWx3YXlzIHNlbnQgd2l0aG91dCBvdGhlciBhdHRhY2htZW50c1xuICAgICAgaWYgKHRoaXMub3JkZXJlZEF0dGFjaG1lbnRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICB0aGlzLm9yZGVyZWRBdHRhY2htZW50cy5wdXNoKFxuICAgICAgICAgIC4uLmJ1aWx0SW5BdHRhY2htZW50cy5maWx0ZXIoKGEpID0+IHRoaXMuaXNDYXJkKGEpKSxcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICAgIHRoaXMuY3VzdG9tQXR0YWNobWVudHMgPSBjdXN0b21BdHRhY2htZW50cztcbiAgICB9XG4gIH1cblxuICBuZ09uSW5pdCgpOiB2b2lkIHtcbiAgICB0aGlzLnN1YnNjcmlwdGlvbnMucHVzaChcbiAgICAgIHRoaXMuY3VzdG9tVGVtcGxhdGVzU2VydmljZS5jdXN0b21BdHRhY2htZW50TGlzdFRlbXBsYXRlJC5zdWJzY3JpYmUoXG4gICAgICAgICh0KSA9PiAodGhpcy5jdXN0b21BdHRhY2htZW50c1RlbXBsYXRlID0gdCksXG4gICAgICApLFxuICAgICk7XG4gIH1cblxuICBuZ09uRGVzdHJveSgpOiB2b2lkIHtcbiAgICB0aGlzLnN1YnNjcmlwdGlvbnMuZm9yRWFjaCgocykgPT4gcy51bnN1YnNjcmliZSgpKTtcbiAgfVxuXG4gIGlzSW1hZ2UoYXR0YWNobWVudDogQXR0YWNobWVudCkge1xuICAgIHJldHVybiBpc0ltYWdlQXR0YWNobWVudChhdHRhY2htZW50KTtcbiAgfVxuXG4gIGlzU3ZnKGF0dGFjaG1lbnQ6IEF0dGFjaG1lbnQpIHtcbiAgICBjb25zdCBmaWxlbmFtZSA9IGF0dGFjaG1lbnQuZmFsbGJhY2sgfHwgJyc7XG4gICAgcmV0dXJuICEhZmlsZW5hbWUudG9Mb3dlckNhc2UoKS5lbmRzV2l0aCgnLnN2ZycpO1xuICB9XG5cbiAgaXNGaWxlKGF0dGFjaG1lbnQ6IEF0dGFjaG1lbnQpIHtcbiAgICByZXR1cm4gYXR0YWNobWVudC50eXBlID09PSAnZmlsZSc7XG4gIH1cblxuICBpc0dhbGxlcnkoYXR0YWNobWVudDogQXR0YWNobWVudCkge1xuICAgIHJldHVybiBhdHRhY2htZW50LnR5cGUgPT09ICdnYWxsZXJ5JztcbiAgfVxuXG4gIGlzVmlkZW8oYXR0YWNobWVudDogQXR0YWNobWVudCkge1xuICAgIHJldHVybiAoXG4gICAgICBhdHRhY2htZW50LnR5cGUgPT09ICd2aWRlbycgJiZcbiAgICAgIGF0dGFjaG1lbnQuYXNzZXRfdXJsICYmXG4gICAgICAhYXR0YWNobWVudC5vZ19zY3JhcGVfdXJsXG4gICAgKTtcbiAgfVxuXG4gIGlzQ2FyZChhdHRhY2htZW50OiBBdHRhY2htZW50KSB7XG4gICAgcmV0dXJuIChcbiAgICAgICFhdHRhY2htZW50LnR5cGUgfHxcbiAgICAgIChhdHRhY2htZW50LnR5cGUgPT09ICdpbWFnZScgJiYgIXRoaXMuaXNJbWFnZShhdHRhY2htZW50KSkgfHxcbiAgICAgIGF0dGFjaG1lbnQudHlwZSA9PT0gJ2dpcGh5JyB8fFxuICAgICAgKGF0dGFjaG1lbnQudHlwZSA9PT0gJ3ZpZGVvJyAmJiBhdHRhY2htZW50Lm9nX3NjcmFwZV91cmwpXG4gICAgKTtcbiAgfVxuXG4gIGlzVm9pY2VNZXNzYWdlKGF0dGFjaG1lbnQ6IEF0dGFjaG1lbnQpIHtcbiAgICByZXR1cm4gYXR0YWNobWVudC50eXBlID09PSAndm9pY2VSZWNvcmRpbmcnO1xuICB9XG5cbiAgaGFzRmlsZVNpemUoYXR0YWNobWVudDogQXR0YWNobWVudDxEZWZhdWx0U3RyZWFtQ2hhdEdlbmVyaWNzPikge1xuICAgIHJldHVybiAoXG4gICAgICBhdHRhY2htZW50LmZpbGVfc2l6ZSAmJiBOdW1iZXIuaXNGaW5pdGUoTnVtYmVyKGF0dGFjaG1lbnQuZmlsZV9zaXplKSlcbiAgICApO1xuICB9XG5cbiAgZ2V0RmlsZVNpemUoYXR0YWNobWVudDogQXR0YWNobWVudDxEZWZhdWx0U3RyZWFtQ2hhdEdlbmVyaWNzPikge1xuICAgIHJldHVybiBwcmV0dHlieXRlcyhOdW1iZXIoYXR0YWNobWVudC5maWxlX3NpemUhKSk7XG4gIH1cblxuICBnZXRNb2RhbENvbnRleHQoKTogTW9kYWxDb250ZXh0IHtcbiAgICByZXR1cm4ge1xuICAgICAgaXNPcGVuOiB0aGlzLmltYWdlc1RvVmlldyAmJiB0aGlzLmltYWdlc1RvVmlldy5sZW5ndGggPiAwLFxuICAgICAgaXNPcGVuQ2hhbmdlSGFuZGxlcjogKGlzT3BlbikgPT4gKGlzT3BlbiA/IG51bGwgOiB0aGlzLmNsb3NlSW1hZ2VNb2RhbCgpKSxcbiAgICAgIGNvbnRlbnQ6IHRoaXMubW9kYWxDb250ZW50LFxuICAgIH07XG4gIH1cblxuICB0cmltVXJsKHVybD86IHN0cmluZyB8IG51bGwpIHtcbiAgICBpZiAodXJsICE9PSB1bmRlZmluZWQgJiYgdXJsICE9PSBudWxsKSB7XG4gICAgICBjb25zdCBbdHJpbW1lZFVybF0gPSB1cmxcbiAgICAgICAgLnJlcGxhY2UoL14oPzpodHRwcz86XFwvXFwvKT8oPzp3d3dcXC4pPy9pLCAnJylcbiAgICAgICAgLnNwbGl0KCcvJyk7XG5cbiAgICAgIHJldHVybiB0cmltbWVkVXJsO1xuICAgIH1cbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIHNlbmRBY3Rpb24oYWN0aW9uOiBBY3Rpb24pIHtcbiAgICB2b2lkIHRoaXMuY2hhbm5lbFNlcnZpY2Uuc2VuZEFjdGlvbihcbiAgICAgIHRoaXMubWVzc2FnZUlkISxcbiAgICAgIHtcbiAgICAgICAgW2FjdGlvbi5uYW1lIV06IGFjdGlvbi52YWx1ZSEsXG4gICAgICB9LFxuICAgICAgdGhpcy5wYXJlbnRNZXNzYWdlSWQsXG4gICAgKTtcbiAgfVxuXG4gIG9wZW5JbWFnZU1vZGFsKGF0dGFjaG1lbnRzOiBBdHRhY2htZW50W10sIHNlbGVjdGVkSW5kZXggPSAwKSB7XG4gICAgdGhpcy5pbWFnZU1vZGFsU3RhdGVDaGFuZ2UubmV4dCgnb3BlbmVkJyk7XG4gICAgdGhpcy5pbWFnZXNUb1ZpZXcgPSBhdHRhY2htZW50cztcbiAgICB0aGlzLmltYWdlc1RvVmlld0N1cnJlbnRJbmRleCA9IHNlbGVjdGVkSW5kZXg7XG4gIH1cblxuICBzdGVwSW1hZ2VzKGRpcjogLTEgfCAxKSB7XG4gICAgdGhpcy5pbWFnZXNUb1ZpZXdDdXJyZW50SW5kZXggKz0gZGlyICogMTtcbiAgfVxuXG4gIGdldEF0dGFjaG1lbnRDb250ZXh0KFxuICAgIGF0dGFjaG1lbnQ6IEF0dGFjaG1lbnQ8RGVmYXVsdFN0cmVhbUNoYXRHZW5lcmljcz4sXG4gICk6IEF0dGFjaG1lbnRDb250ZXh0IHtcbiAgICByZXR1cm4geyBhdHRhY2htZW50IH07XG4gIH1cblxuICBnZXRJbWFnZUF0dGFjaG1lbnRDb25maWd1cmF0aW9uKFxuICAgIGF0dGFjaG1lbnQ6IEF0dGFjaG1lbnQsXG4gICAgdHlwZTogJ2dhbGxlcnknIHwgJ3NpbmdsZScsXG4gICAgZWxlbWVudDogSFRNTEVsZW1lbnQsXG4gICk6IEltYWdlQXR0YWNobWVudENvbmZpZ3VyYXRpb24ge1xuICAgIGNvbnN0IGV4aXN0aW5nQ29uZmlndXJhdGlvbiA9IHRoaXMuYXR0YWNobWVudENvbmZpZ3VyYXRpb25zLmdldChhdHRhY2htZW50KTtcbiAgICBpZiAoZXhpc3RpbmdDb25maWd1cmF0aW9uKSB7XG4gICAgICByZXR1cm4gZXhpc3RpbmdDb25maWd1cmF0aW9uIGFzIEltYWdlQXR0YWNobWVudENvbmZpZ3VyYXRpb247XG4gICAgfVxuICAgIGNvbnN0IGNvbmZpZ3VyYXRpb24gPVxuICAgICAgdGhpcy5hdHRhY2htZW50Q29uZmlndXJhdGlvblNlcnZpY2UuZ2V0SW1hZ2VBdHRhY2htZW50Q29uZmlndXJhdGlvbihcbiAgICAgICAgYXR0YWNobWVudCxcbiAgICAgICAgdHlwZSxcbiAgICAgICAgZWxlbWVudCxcbiAgICAgICk7XG4gICAgdGhpcy5hdHRhY2htZW50Q29uZmlndXJhdGlvbnMuc2V0KGF0dGFjaG1lbnQsIGNvbmZpZ3VyYXRpb24pO1xuICAgIHJldHVybiBjb25maWd1cmF0aW9uO1xuICB9XG5cbiAgZ2V0Q2Fyb3VzZWxJbWFnZUF0dGFjaG1lbnRDb25maWd1cmF0aW9uKFxuICAgIGF0dGFjaG1lbnQ6IEF0dGFjaG1lbnQsXG4gICAgZWxlbWVudDogSFRNTEVsZW1lbnQsXG4gICkge1xuICAgIHJldHVybiB0aGlzLmF0dGFjaG1lbnRDb25maWd1cmF0aW9uU2VydmljZS5nZXRJbWFnZUF0dGFjaG1lbnRDb25maWd1cmF0aW9uKFxuICAgICAgYXR0YWNobWVudCxcbiAgICAgICdjYXJvdXNlbCcsXG4gICAgICBlbGVtZW50LFxuICAgICk7XG4gIH1cblxuICBnZXRWaWRlb0F0dGFjaG1lbnRDb25maWd1cmF0aW9uKFxuICAgIGF0dGFjaG1lbnQ6IEF0dGFjaG1lbnQsXG4gICAgZWxlbWVudDogSFRNTEVsZW1lbnQsXG4gICk6IFZpZGVvQXR0YWNobWVudENvbmZpZ3VyYXRpb24ge1xuICAgIGNvbnN0IGV4aXN0aW5nQ29uZmlndXJhdGlvbiA9IHRoaXMuYXR0YWNobWVudENvbmZpZ3VyYXRpb25zLmdldChhdHRhY2htZW50KTtcbiAgICBpZiAoZXhpc3RpbmdDb25maWd1cmF0aW9uKSB7XG4gICAgICByZXR1cm4gZXhpc3RpbmdDb25maWd1cmF0aW9uIGFzIFZpZGVvQXR0YWNobWVudENvbmZpZ3VyYXRpb247XG4gICAgfVxuICAgIGNvbnN0IGNvbmZpZ3VyYXRpb24gPVxuICAgICAgdGhpcy5hdHRhY2htZW50Q29uZmlndXJhdGlvblNlcnZpY2UuZ2V0VmlkZW9BdHRhY2htZW50Q29uZmlndXJhdGlvbihcbiAgICAgICAgYXR0YWNobWVudCxcbiAgICAgICAgZWxlbWVudCxcbiAgICAgICk7XG4gICAgdGhpcy5hdHRhY2htZW50Q29uZmlndXJhdGlvbnMuc2V0KGF0dGFjaG1lbnQsIGNvbmZpZ3VyYXRpb24pO1xuICAgIHJldHVybiBjb25maWd1cmF0aW9uO1xuICB9XG5cbiAgZ2V0Q2FyZEF0dGFjaG1lbnRDb25maWd1cmF0aW9uKGF0dGFjaG1lbnQ6IEF0dGFjaG1lbnQpIHtcbiAgICBjb25zdCBleGlzdGluZ0NvbmZpZ3VyYXRpb24gPSB0aGlzLmF0dGFjaG1lbnRDb25maWd1cmF0aW9ucy5nZXQoYXR0YWNobWVudCk7XG4gICAgaWYgKGV4aXN0aW5nQ29uZmlndXJhdGlvbikge1xuICAgICAgcmV0dXJuIGV4aXN0aW5nQ29uZmlndXJhdGlvbjtcbiAgICB9XG4gICAgaWYgKGF0dGFjaG1lbnQudHlwZSA9PT0gJ2dpcGh5Jykge1xuICAgICAgcmV0dXJuIHRoaXMuYXR0YWNobWVudENvbmZpZ3VyYXRpb25TZXJ2aWNlLmdldEdpcGh5QXR0YWNobWVudENvbmZpZ3VyYXRpb24oXG4gICAgICAgIGF0dGFjaG1lbnQsXG4gICAgICApO1xuICAgIH0gZWxzZSB7XG4gICAgICBjb25zdCBjb25maWd1cmF0aW9uID1cbiAgICAgICAgdGhpcy5hdHRhY2htZW50Q29uZmlndXJhdGlvblNlcnZpY2UuZ2V0U2NyYXBlZEltYWdlQXR0YWNobWVudENvbmZpZ3VyYXRpb24oXG4gICAgICAgICAgYXR0YWNobWVudCxcbiAgICAgICAgKTtcbiAgICAgIHRoaXMuYXR0YWNobWVudENvbmZpZ3VyYXRpb25zLnNldChhdHRhY2htZW50LCBjb25maWd1cmF0aW9uKTtcbiAgICAgIHJldHVybiBjb25maWd1cmF0aW9uO1xuICAgIH1cbiAgfVxuXG4gIGdldCBpc0ltYWdlTW9kYWxQcmV2QnV0dG9uVmlzaWJsZSgpIHtcbiAgICByZXR1cm4gdGhpcy5pbWFnZXNUb1ZpZXdDdXJyZW50SW5kZXggIT09IDA7XG4gIH1cblxuICBnZXQgaXNJbWFnZU1vZGFsTmV4dEJ1dHRvblZpc2libGUoKSB7XG4gICAgcmV0dXJuIHRoaXMuaW1hZ2VzVG9WaWV3Q3VycmVudEluZGV4ICE9PSB0aGlzLmltYWdlc1RvVmlldy5sZW5ndGggLSAxO1xuICB9XG5cbiAgcHJpdmF0ZSBjcmVhdGVHYWxsZXJ5KGltYWdlczogQXR0YWNobWVudFtdKSB7XG4gICAgcmV0dXJuIFtcbiAgICAgIHtcbiAgICAgICAgdHlwZTogJ2dhbGxlcnknLFxuICAgICAgICBpbWFnZXMsXG4gICAgICB9LFxuICAgIF07XG4gIH1cblxuICBwcml2YXRlIGNsb3NlSW1hZ2VNb2RhbCgpIHtcbiAgICB0aGlzLmltYWdlTW9kYWxTdGF0ZUNoYW5nZS5uZXh0KCdjbG9zZWQnKTtcbiAgICB0aGlzLmltYWdlc1RvVmlldyA9IFtdO1xuICB9XG59XG4iLCJAaWYgKFxuICBvcmRlcmVkQXR0YWNobWVudHMubGVuZ3RoID4gMCB8fFxuICAoY3VzdG9tQXR0YWNobWVudHMubGVuZ3RoID4gMCAmJiBjdXN0b21BdHRhY2htZW50c1RlbXBsYXRlKVxuKSB7XG4gIDxkaXYgY2xhc3M9XCJzdHItY2hhdF9fYXR0YWNobWVudC1saXN0XCI+XG4gICAgQGZvciAoXG4gICAgICBhdHRhY2htZW50IG9mIG9yZGVyZWRBdHRhY2htZW50cztcbiAgICAgIHRyYWNrIGF0dGFjaG1lbnQuaW1hZ2VfdXJsIHx8XG4gICAgICAgIGF0dGFjaG1lbnQuaW1nX3VybCB8fFxuICAgICAgICBhdHRhY2htZW50LmFzc2V0X3VybCB8fFxuICAgICAgICBhdHRhY2htZW50LnRodW1iX3VybFxuICAgICkge1xuICAgICAgPGRpdlxuICAgICAgICBkYXRhLXRlc3RjbGFzcz1cImF0dGFjaG1lbnQtY29udGFpbmVyXCJcbiAgICAgICAgY2xhc3M9XCJzdHItY2hhdF9fbWVzc2FnZS1hdHRhY2htZW50IHN0ci1jaGF0X19tZXNzYWdlLWF0dGFjaG1lbnQtLXt7XG4gICAgICAgICAgYXR0YWNobWVudC50eXBlXG4gICAgICAgIH19IHN0ci1jaGF0X19tZXNzYWdlLWF0dGFjaG1lbnQtZHluYW1pYy1zaXplXCJcbiAgICAgICAgW2NsYXNzLnN0ci1jaGF0X19tZXNzYWdlLWF0dGFjaG1lbnQtLWNhcmRdPVwiaXNDYXJkKGF0dGFjaG1lbnQpXCJcbiAgICAgICAgW2NsYXNzLnN0ci1jaGF0LWFuZ3VsYXJfX21lc3NhZ2UtYXR0YWNobWVudC1maWxlLXNpbmdsZV09XCJcbiAgICAgICAgICBpc0ZpbGUoYXR0YWNobWVudClcbiAgICAgICAgXCJcbiAgICAgICAgW2NsYXNzLnN0ci1jaGF0X19tZXNzYWdlLWF0dGFjaG1lbnQtLXZvaWNlLXJlY29yZGluZ109XCJcbiAgICAgICAgICBpc1ZvaWNlTWVzc2FnZShhdHRhY2htZW50KVxuICAgICAgICBcIlxuICAgICAgICBbY2xhc3Muc3RyLWNoYXRfX21lc3NhZ2UtYXR0YWNobWVudC13aXRoLWFjdGlvbnNdPVwiXG4gICAgICAgICAgYXR0YWNobWVudC5hY3Rpb25zICYmIGF0dGFjaG1lbnQuYWN0aW9ucy5sZW5ndGggPiAwXG4gICAgICAgIFwiXG4gICAgICAgIFtjbGFzcy5zdHItY2hhdF9fbWVzc2FnZS1hdHRhY2htZW50LS1zdmctaW1hZ2VdPVwiaXNTdmcoYXR0YWNobWVudClcIlxuICAgICAgPlxuICAgICAgICBAaWYgKGlzSW1hZ2UoYXR0YWNobWVudCkpIHtcbiAgICAgICAgICA8bmctY29udGFpbmVyXG4gICAgICAgICAgICAqbmdUZW1wbGF0ZU91dGxldD1cIlxuICAgICAgICAgICAgICAoY3VzdG9tVGVtcGxhdGVzU2VydmljZS5pbWFnZUF0dGFjaG1lbnRUZW1wbGF0ZSQgfCBhc3luYykgfHxcbiAgICAgICAgICAgICAgICBkZWZhdWx0SW1hZ2U7XG4gICAgICAgICAgICAgIGNvbnRleHQ6IGdldEF0dGFjaG1lbnRDb250ZXh0KGF0dGFjaG1lbnQpXG4gICAgICAgICAgICBcIlxuICAgICAgICAgIC8+XG4gICAgICAgICAgPG5nLXRlbXBsYXRlICNkZWZhdWx0SW1hZ2UgbGV0LWF0dGFjaG1lbnRDb250ZXh0PVwiYXR0YWNobWVudFwiPlxuICAgICAgICAgICAgPGltZ1xuICAgICAgICAgICAgICAjaW1nRWxlbWVudFxuICAgICAgICAgICAgICBjbGFzcz1cInN0ci1jaGF0X19tZXNzYWdlLWF0dGFjaG1lbnQtLWltZ1wiXG4gICAgICAgICAgICAgIGRhdGEtdGVzdGNsYXNzPVwiaW1hZ2VcIlxuICAgICAgICAgICAgICBbc3JjXT1cIlxuICAgICAgICAgICAgICAgIGdldEltYWdlQXR0YWNobWVudENvbmZpZ3VyYXRpb24oXG4gICAgICAgICAgICAgICAgICBhdHRhY2htZW50Q29udGV4dCxcbiAgICAgICAgICAgICAgICAgICdzaW5nbGUnLFxuICAgICAgICAgICAgICAgICAgaW1nRWxlbWVudFxuICAgICAgICAgICAgICAgICkudXJsXG4gICAgICAgICAgICAgIFwiXG4gICAgICAgICAgICAgIFthbHRdPVwiYXR0YWNobWVudENvbnRleHQ/LmZhbGxiYWNrXCJcbiAgICAgICAgICAgICAgW25nU3R5bGVdPVwie1xuICAgICAgICAgICAgICAgIGhlaWdodDogZ2V0SW1hZ2VBdHRhY2htZW50Q29uZmlndXJhdGlvbihcbiAgICAgICAgICAgICAgICAgIGF0dGFjaG1lbnRDb250ZXh0LFxuICAgICAgICAgICAgICAgICAgJ3NpbmdsZScsXG4gICAgICAgICAgICAgICAgICBpbWdFbGVtZW50XG4gICAgICAgICAgICAgICAgKS5oZWlnaHQsXG4gICAgICAgICAgICAgICAgd2lkdGg6IGdldEltYWdlQXR0YWNobWVudENvbmZpZ3VyYXRpb24oXG4gICAgICAgICAgICAgICAgICBhdHRhY2htZW50Q29udGV4dCxcbiAgICAgICAgICAgICAgICAgICdzaW5nbGUnLFxuICAgICAgICAgICAgICAgICAgaW1nRWxlbWVudFxuICAgICAgICAgICAgICAgICkud2lkdGgsXG4gICAgICAgICAgICAgICAgJy0tb3JpZ2luYWwtaGVpZ2h0JzogZ2V0SW1hZ2VBdHRhY2htZW50Q29uZmlndXJhdGlvbihcbiAgICAgICAgICAgICAgICAgIGF0dGFjaG1lbnRDb250ZXh0LFxuICAgICAgICAgICAgICAgICAgJ3NpbmdsZScsXG4gICAgICAgICAgICAgICAgICBpbWdFbGVtZW50XG4gICAgICAgICAgICAgICAgKS5vcmlnaW5hbEhlaWdodCxcbiAgICAgICAgICAgICAgICAnLS1vcmlnaW5hbC13aWR0aCc6IGdldEltYWdlQXR0YWNobWVudENvbmZpZ3VyYXRpb24oXG4gICAgICAgICAgICAgICAgICBhdHRhY2htZW50Q29udGV4dCxcbiAgICAgICAgICAgICAgICAgICdzaW5nbGUnLFxuICAgICAgICAgICAgICAgICAgaW1nRWxlbWVudFxuICAgICAgICAgICAgICAgICkub3JpZ2luYWxXaWR0aCxcbiAgICAgICAgICAgICAgfVwiXG4gICAgICAgICAgICAgIChjbGljayk9XCJvcGVuSW1hZ2VNb2RhbChbYXR0YWNobWVudENvbnRleHRdKVwiXG4gICAgICAgICAgICAgIChrZXl1cC5lbnRlcik9XCJvcGVuSW1hZ2VNb2RhbChbYXR0YWNobWVudENvbnRleHRdKVwiXG4gICAgICAgICAgICAvPlxuICAgICAgICAgIDwvbmctdGVtcGxhdGU+XG4gICAgICAgIH1cbiAgICAgICAgQGlmIChpc0dhbGxlcnkoYXR0YWNobWVudCkpIHtcbiAgICAgICAgICA8bmctY29udGFpbmVyXG4gICAgICAgICAgICAqbmdUZW1wbGF0ZU91dGxldD1cIlxuICAgICAgICAgICAgICAoY3VzdG9tVGVtcGxhdGVzU2VydmljZS5nYWxsZXJ5QXR0YWNobWVudFRlbXBsYXRlJCB8IGFzeW5jKSB8fFxuICAgICAgICAgICAgICAgIGRlZmF1bHRHYWxsZXJ5O1xuICAgICAgICAgICAgICBjb250ZXh0OiBnZXRBdHRhY2htZW50Q29udGV4dChhdHRhY2htZW50KVxuICAgICAgICAgICAgXCJcbiAgICAgICAgICAvPlxuICAgICAgICAgIDxuZy10ZW1wbGF0ZSAjZGVmYXVsdEdhbGxlcnkgbGV0LWF0dGFjaG1lbnRDb250ZXh0PVwiYXR0YWNobWVudFwiPlxuICAgICAgICAgICAgPGRpdlxuICAgICAgICAgICAgICBjbGFzcz1cInN0ci1jaGF0X19nYWxsZXJ5XCJcbiAgICAgICAgICAgICAgZGF0YS10ZXN0aWQ9XCJpbWFnZS1nYWxsZXJ5XCJcbiAgICAgICAgICAgICAgW2NsYXNzLnN0ci1jaGF0X19nYWxsZXJ5LS1zcXVhcmVdPVwiXG4gICAgICAgICAgICAgICAgKGF0dGFjaG1lbnRDb250ZXh0Py5pbWFnZXMpIS5sZW5ndGggPiAzXG4gICAgICAgICAgICAgIFwiXG4gICAgICAgICAgICAgIFtjbGFzcy5zdHItY2hhdF9fZ2FsbGVyeS10d28tcm93c109XCJcbiAgICAgICAgICAgICAgICAoYXR0YWNobWVudENvbnRleHQ/LmltYWdlcykhLmxlbmd0aCA+IDJcbiAgICAgICAgICAgICAgXCJcbiAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgQGZvciAoXG4gICAgICAgICAgICAgICAgZ2FsbGVyeUltYWdlIG9mIGF0dGFjaG1lbnRDb250ZXh0LmltYWdlcztcbiAgICAgICAgICAgICAgICB0cmFjayBnYWxsZXJ5SW1hZ2UuaW1hZ2VfdXJsIHx8XG4gICAgICAgICAgICAgICAgICBnYWxsZXJ5SW1hZ2UuaW1nX3VybCB8fFxuICAgICAgICAgICAgICAgICAgZ2FsbGVyeUltYWdlLnRodW1iX3VybDtcbiAgICAgICAgICAgICAgICBsZXQgaW5kZXggPSAkaW5kZXg7XG4gICAgICAgICAgICAgICAgbGV0IGlzTGFzdCA9ICRsYXN0XG4gICAgICAgICAgICAgICkge1xuICAgICAgICAgICAgICAgIEBpZiAoaW5kZXggPCAzIHx8IChpbmRleCA9PT0gMyAmJiBpc0xhc3QpKSB7XG4gICAgICAgICAgICAgICAgICA8YnV0dG9uXG4gICAgICAgICAgICAgICAgICAgIGNsYXNzPVwic3RyLWNoYXRfX2dhbGxlcnktaW1hZ2VcIlxuICAgICAgICAgICAgICAgICAgICBkYXRhLXRlc3RjbGFzcz1cImdhbGxlcnktaW1hZ2VcIlxuICAgICAgICAgICAgICAgICAgICBbY2xhc3Muc3RyLWNoYXRfX21lc3NhZ2UtYXR0YWNobWVudC0tc3ZnLWltYWdlXT1cIlxuICAgICAgICAgICAgICAgICAgICAgIGlzU3ZnKGdhbGxlcnlJbWFnZSlcbiAgICAgICAgICAgICAgICAgICAgXCJcbiAgICAgICAgICAgICAgICAgICAgKGNsaWNrKT1cIm9wZW5JbWFnZU1vZGFsKGF0dGFjaG1lbnRDb250ZXh0LmltYWdlcyEsIGluZGV4KVwiXG4gICAgICAgICAgICAgICAgICAgIChrZXl1cC5lbnRlcik9XCJcbiAgICAgICAgICAgICAgICAgICAgICBvcGVuSW1hZ2VNb2RhbChhdHRhY2htZW50Q29udGV4dC5pbWFnZXMhLCBpbmRleClcbiAgICAgICAgICAgICAgICAgICAgXCJcbiAgICAgICAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgICAgICAgPGltZ1xuICAgICAgICAgICAgICAgICAgICAgICNpbWdFbGVtZW50XG4gICAgICAgICAgICAgICAgICAgICAgZmV0Y2hwcmlvcml0eT1cImxvd1wiXG4gICAgICAgICAgICAgICAgICAgICAgbG9hZGluZz1cImxhenlcIlxuICAgICAgICAgICAgICAgICAgICAgIFtzcmNdPVwiXG4gICAgICAgICAgICAgICAgICAgICAgICBnZXRJbWFnZUF0dGFjaG1lbnRDb25maWd1cmF0aW9uKFxuICAgICAgICAgICAgICAgICAgICAgICAgICBnYWxsZXJ5SW1hZ2UsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICdnYWxsZXJ5JyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgaW1nRWxlbWVudFxuICAgICAgICAgICAgICAgICAgICAgICAgKS51cmxcbiAgICAgICAgICAgICAgICAgICAgICBcIlxuICAgICAgICAgICAgICAgICAgICAgIFthbHRdPVwiZ2FsbGVyeUltYWdlLmZhbGxiYWNrXCJcbiAgICAgICAgICAgICAgICAgICAgICBbc3R5bGUuLS1vcmlnaW5hbC1oZWlnaHRdPVwiXG4gICAgICAgICAgICAgICAgICAgICAgICBnZXRJbWFnZUF0dGFjaG1lbnRDb25maWd1cmF0aW9uKFxuICAgICAgICAgICAgICAgICAgICAgICAgICBnYWxsZXJ5SW1hZ2UsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICdnYWxsZXJ5JyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgaW1nRWxlbWVudFxuICAgICAgICAgICAgICAgICAgICAgICAgKS5vcmlnaW5hbEhlaWdodFxuICAgICAgICAgICAgICAgICAgICAgIFwiXG4gICAgICAgICAgICAgICAgICAgICAgW3N0eWxlLi0tb3JpZ2luYWwtd2lkdGhdPVwiXG4gICAgICAgICAgICAgICAgICAgICAgICBnZXRJbWFnZUF0dGFjaG1lbnRDb25maWd1cmF0aW9uKFxuICAgICAgICAgICAgICAgICAgICAgICAgICBnYWxsZXJ5SW1hZ2UsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICdnYWxsZXJ5JyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgaW1nRWxlbWVudFxuICAgICAgICAgICAgICAgICAgICAgICAgKS5vcmlnaW5hbFdpZHRoXG4gICAgICAgICAgICAgICAgICAgICAgXCJcbiAgICAgICAgICAgICAgICAgICAgICBbbmdTdHlsZV09XCJ7XG4gICAgICAgICAgICAgICAgICAgICAgICBoZWlnaHQ6IGdldEltYWdlQXR0YWNobWVudENvbmZpZ3VyYXRpb24oXG4gICAgICAgICAgICAgICAgICAgICAgICAgIGdhbGxlcnlJbWFnZSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgJ2dhbGxlcnknLFxuICAgICAgICAgICAgICAgICAgICAgICAgICBpbWdFbGVtZW50XG4gICAgICAgICAgICAgICAgICAgICAgICApLmhlaWdodCxcbiAgICAgICAgICAgICAgICAgICAgICAgIHdpZHRoOiBnZXRJbWFnZUF0dGFjaG1lbnRDb25maWd1cmF0aW9uKFxuICAgICAgICAgICAgICAgICAgICAgICAgICBnYWxsZXJ5SW1hZ2UsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICdnYWxsZXJ5JyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgaW1nRWxlbWVudFxuICAgICAgICAgICAgICAgICAgICAgICAgKS53aWR0aCxcbiAgICAgICAgICAgICAgICAgICAgICB9XCJcbiAgICAgICAgICAgICAgICAgICAgLz5cbiAgICAgICAgICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBAaWYgKGluZGV4ID09PSAzICYmICFpc0xhc3QpIHtcbiAgICAgICAgICAgICAgICAgIDxidXR0b25cbiAgICAgICAgICAgICAgICAgICAgI2VsZW1lbnRcbiAgICAgICAgICAgICAgICAgICAgY2xhc3M9XCJzdHItY2hhdF9fZ2FsbGVyeS1wbGFjZWhvbGRlclwiXG4gICAgICAgICAgICAgICAgICAgIGRhdGEtdGVzdGNsYXNzPVwiZ2FsbGVyeS1pbWFnZVwiXG4gICAgICAgICAgICAgICAgICAgIGRhdGEtdGVzdGlkPVwibW9yZS1pbWFnZS1idXR0b25cIlxuICAgICAgICAgICAgICAgICAgICBbY2xhc3Muc3RyLWNoYXRfX21lc3NhZ2UtYXR0YWNobWVudC0tc3ZnLWltYWdlXT1cIlxuICAgICAgICAgICAgICAgICAgICAgIGlzU3ZnKGdhbGxlcnlJbWFnZSlcbiAgICAgICAgICAgICAgICAgICAgXCJcbiAgICAgICAgICAgICAgICAgICAgW25nU3R5bGVdPVwie1xuICAgICAgICAgICAgICAgICAgICAgICdiYWNrZ3JvdW5kLWltYWdlJzpcbiAgICAgICAgICAgICAgICAgICAgICAgICd1cmwoJyArXG4gICAgICAgICAgICAgICAgICAgICAgICBnZXRJbWFnZUF0dGFjaG1lbnRDb25maWd1cmF0aW9uKFxuICAgICAgICAgICAgICAgICAgICAgICAgICBnYWxsZXJ5SW1hZ2UsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICdnYWxsZXJ5JyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgZWxlbWVudFxuICAgICAgICAgICAgICAgICAgICAgICAgKS51cmwgK1xuICAgICAgICAgICAgICAgICAgICAgICAgJyknLFxuICAgICAgICAgICAgICAgICAgICAgIGhlaWdodDogZ2V0SW1hZ2VBdHRhY2htZW50Q29uZmlndXJhdGlvbihcbiAgICAgICAgICAgICAgICAgICAgICAgIGdhbGxlcnlJbWFnZSxcbiAgICAgICAgICAgICAgICAgICAgICAgICdnYWxsZXJ5JyxcbiAgICAgICAgICAgICAgICAgICAgICAgIGVsZW1lbnRcbiAgICAgICAgICAgICAgICAgICAgICApLmhlaWdodCxcbiAgICAgICAgICAgICAgICAgICAgICB3aWR0aDogZ2V0SW1hZ2VBdHRhY2htZW50Q29uZmlndXJhdGlvbihcbiAgICAgICAgICAgICAgICAgICAgICAgIGdhbGxlcnlJbWFnZSxcbiAgICAgICAgICAgICAgICAgICAgICAgICdnYWxsZXJ5JyxcbiAgICAgICAgICAgICAgICAgICAgICAgIGVsZW1lbnRcbiAgICAgICAgICAgICAgICAgICAgICApLndpZHRoLFxuICAgICAgICAgICAgICAgICAgICAgICctLW9yaWdpbmFsLWhlaWdodCc6IGdldEltYWdlQXR0YWNobWVudENvbmZpZ3VyYXRpb24oXG4gICAgICAgICAgICAgICAgICAgICAgICBnYWxsZXJ5SW1hZ2UsXG4gICAgICAgICAgICAgICAgICAgICAgICAnZ2FsbGVyeScsXG4gICAgICAgICAgICAgICAgICAgICAgICBlbGVtZW50XG4gICAgICAgICAgICAgICAgICAgICAgKS5vcmlnaW5hbEhlaWdodCxcbiAgICAgICAgICAgICAgICAgICAgICAnLS1vcmlnaW5hbC13aWR0aCc6IGdldEltYWdlQXR0YWNobWVudENvbmZpZ3VyYXRpb24oXG4gICAgICAgICAgICAgICAgICAgICAgICBnYWxsZXJ5SW1hZ2UsXG4gICAgICAgICAgICAgICAgICAgICAgICAnZ2FsbGVyeScsXG4gICAgICAgICAgICAgICAgICAgICAgICBlbGVtZW50XG4gICAgICAgICAgICAgICAgICAgICAgKS5vcmlnaW5hbFdpZHRoLFxuICAgICAgICAgICAgICAgICAgICB9XCJcbiAgICAgICAgICAgICAgICAgICAgKGNsaWNrKT1cIm9wZW5JbWFnZU1vZGFsKGF0dGFjaG1lbnRDb250ZXh0LmltYWdlcyEsIGluZGV4KVwiXG4gICAgICAgICAgICAgICAgICAgIChrZXl1cC5lbnRlcik9XCJcbiAgICAgICAgICAgICAgICAgICAgICBvcGVuSW1hZ2VNb2RhbChhdHRhY2htZW50Q29udGV4dC5pbWFnZXMhLCBpbmRleClcbiAgICAgICAgICAgICAgICAgICAgXCJcbiAgICAgICAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgICAgICAgPHBcbiAgICAgICAgICAgICAgICAgICAgICBbaW5uZXJIVE1MXT1cIlxuICAgICAgICAgICAgICAgICAgICAgICAgJ3N0cmVhbUNoYXQue3sgaW1hZ2VDb3VudCB9fSBtb3JlJ1xuICAgICAgICAgICAgICAgICAgICAgICAgICB8IHRyYW5zbGF0ZVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDoge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbWFnZUNvdW50OlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGF0dGFjaG1lbnRDb250ZXh0IS5pbWFnZXMhLmxlbmd0aCAtIDQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgXCJcbiAgICAgICAgICAgICAgICAgICAgPjwvcD5cbiAgICAgICAgICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgPC9uZy10ZW1wbGF0ZT5cbiAgICAgICAgfVxuICAgICAgICBAaWYgKGlzVmlkZW8oYXR0YWNobWVudCkpIHtcbiAgICAgICAgICA8bmctY29udGFpbmVyXG4gICAgICAgICAgICAqbmdUZW1wbGF0ZU91dGxldD1cIlxuICAgICAgICAgICAgICAoY3VzdG9tVGVtcGxhdGVzU2VydmljZS52aWRlb0F0dGFjaG1lbnRUZW1wbGF0ZSQgfCBhc3luYykgfHxcbiAgICAgICAgICAgICAgICBkZWZhdWx0VmlkZW87XG4gICAgICAgICAgICAgIGNvbnRleHQ6IGdldEF0dGFjaG1lbnRDb250ZXh0KGF0dGFjaG1lbnQpXG4gICAgICAgICAgICBcIlxuICAgICAgICAgIC8+XG4gICAgICAgICAgPG5nLXRlbXBsYXRlICNkZWZhdWx0VmlkZW8gbGV0LWF0dGFjaG1lbnRDb250ZXh0PVwiYXR0YWNobWVudFwiPlxuICAgICAgICAgICAgPGRpdlxuICAgICAgICAgICAgICBjbGFzcz1cInN0ci1jaGF0X19wbGF5ZXItd3JhcHBlclwiXG4gICAgICAgICAgICAgIGRhdGEtdGVzdGNsYXNzPVwidmlkZW8tYXR0YWNobWVudC1wYXJlbnRcIlxuICAgICAgICAgICAgICBbc3R5bGUuLS1vcmlnaW5hbC1oZWlnaHRdPVwiXG4gICAgICAgICAgICAgICAgZ2V0VmlkZW9BdHRhY2htZW50Q29uZmlndXJhdGlvbihhdHRhY2htZW50Q29udGV4dCwgdmlkZW9FbGVtZW50KVxuICAgICAgICAgICAgICAgICAgLm9yaWdpbmFsSGVpZ2h0XG4gICAgICAgICAgICAgIFwiXG4gICAgICAgICAgICAgIFtzdHlsZS4tLW9yaWdpbmFsLXdpZHRoXT1cIlxuICAgICAgICAgICAgICAgIGdldFZpZGVvQXR0YWNobWVudENvbmZpZ3VyYXRpb24oYXR0YWNobWVudENvbnRleHQsIHZpZGVvRWxlbWVudClcbiAgICAgICAgICAgICAgICAgIC5vcmlnaW5hbFdpZHRoXG4gICAgICAgICAgICAgIFwiXG4gICAgICAgICAgICAgIFtuZ1N0eWxlXT1cIntcbiAgICAgICAgICAgICAgICBoZWlnaHQ6IGdldFZpZGVvQXR0YWNobWVudENvbmZpZ3VyYXRpb24oXG4gICAgICAgICAgICAgICAgICBhdHRhY2htZW50Q29udGV4dCxcbiAgICAgICAgICAgICAgICAgIHZpZGVvRWxlbWVudFxuICAgICAgICAgICAgICAgICkuaGVpZ2h0LFxuICAgICAgICAgICAgICAgIHdpZHRoOiBnZXRWaWRlb0F0dGFjaG1lbnRDb25maWd1cmF0aW9uKFxuICAgICAgICAgICAgICAgICAgYXR0YWNobWVudENvbnRleHQsXG4gICAgICAgICAgICAgICAgICB2aWRlb0VsZW1lbnRcbiAgICAgICAgICAgICAgICApLndpZHRoLFxuICAgICAgICAgICAgICB9XCJcbiAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgPHZpZGVvXG4gICAgICAgICAgICAgICAgI3ZpZGVvRWxlbWVudFxuICAgICAgICAgICAgICAgIGNsYXNzPVwic3RyLWNoYXRfX3ZpZGVvLWFuZ3VsYXJcIlxuICAgICAgICAgICAgICAgIGNvbnRyb2xzXG4gICAgICAgICAgICAgICAgZGF0YS10ZXN0Y2xhc3M9XCJ2aWRlby1hdHRhY2htZW50XCJcbiAgICAgICAgICAgICAgICBbc3JjXT1cIlxuICAgICAgICAgICAgICAgICAgZ2V0VmlkZW9BdHRhY2htZW50Q29uZmlndXJhdGlvbihcbiAgICAgICAgICAgICAgICAgICAgYXR0YWNobWVudENvbnRleHQsXG4gICAgICAgICAgICAgICAgICAgIHZpZGVvRWxlbWVudFxuICAgICAgICAgICAgICAgICAgKS51cmxcbiAgICAgICAgICAgICAgICBcIlxuICAgICAgICAgICAgICAgIFtwb3N0ZXJdPVwiXG4gICAgICAgICAgICAgICAgICBnZXRWaWRlb0F0dGFjaG1lbnRDb25maWd1cmF0aW9uKFxuICAgICAgICAgICAgICAgICAgICBhdHRhY2htZW50Q29udGV4dCxcbiAgICAgICAgICAgICAgICAgICAgdmlkZW9FbGVtZW50XG4gICAgICAgICAgICAgICAgICApLnRodW1iVXJsXG4gICAgICAgICAgICAgICAgXCJcbiAgICAgICAgICAgICAgPjwvdmlkZW8+XG4gICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICA8L25nLXRlbXBsYXRlPlxuICAgICAgICB9XG4gICAgICAgIEBpZiAoaXNGaWxlKGF0dGFjaG1lbnQpKSB7XG4gICAgICAgICAgPG5nLWNvbnRhaW5lclxuICAgICAgICAgICAgKm5nVGVtcGxhdGVPdXRsZXQ9XCJcbiAgICAgICAgICAgICAgKGN1c3RvbVRlbXBsYXRlc1NlcnZpY2UuZmlsZUF0dGFjaG1lbnRUZW1wbGF0ZSQgfCBhc3luYykgfHxcbiAgICAgICAgICAgICAgICBkZWZhdWx0RmlsZTtcbiAgICAgICAgICAgICAgY29udGV4dDogZ2V0QXR0YWNobWVudENvbnRleHQoYXR0YWNobWVudClcbiAgICAgICAgICAgIFwiXG4gICAgICAgICAgLz5cbiAgICAgICAgICA8bmctdGVtcGxhdGUgI2RlZmF1bHRGaWxlIGxldC1hdHRhY2htZW50Q29udGV4dD1cImF0dGFjaG1lbnRcIj5cbiAgICAgICAgICAgIDxkaXZcbiAgICAgICAgICAgICAgY2xhc3M9XCJzdHItY2hhdF9fbWVzc2FnZS1hdHRhY2htZW50LWZpbGUtLWl0ZW0gc3RyLWNoYXQtYW5ndWxhcl9fbWVzc2FnZS1hdHRhY2htZW50LWZpbGUtc2luZ2xlXCJcbiAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgPHN0cmVhbS1pY29uLXBsYWNlaG9sZGVyXG4gICAgICAgICAgICAgICAgY2xhc3M9XCJzdHItY2hhdF9fYXR0YWNobWVudC10eXBlLWljb25cIlxuICAgICAgICAgICAgICAgIGljb249XCJ1bnNwZWNpZmllZC1maWxldHlwZVwiXG4gICAgICAgICAgICAgIC8+XG4gICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJzdHItY2hhdF9fbWVzc2FnZS1hdHRhY2htZW50LWZpbGUtLWl0ZW0tdGV4dFwiPlxuICAgICAgICAgICAgICAgIDxhXG4gICAgICAgICAgICAgICAgICBjbGFzcz1cInN0ci1jaGF0X19tZXNzYWdlLWF0dGFjaG1lbnQtZmlsZS0taXRlbS1maXJzdC1yb3dcIlxuICAgICAgICAgICAgICAgICAgZGF0YS10ZXN0Y2xhc3M9XCJmaWxlLWxpbmtcIlxuICAgICAgICAgICAgICAgICAgdGFyZ2V0PVwiX2JsYW5rXCJcbiAgICAgICAgICAgICAgICAgIGhyZWY9XCJ7eyBhdHRhY2htZW50Q29udGV4dC5hc3NldF91cmwgfX1cIlxuICAgICAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgICAgIDxkaXZcbiAgICAgICAgICAgICAgICAgICAgZGF0YS10ZXN0Y2xhc3M9XCJmaWxlLXRpdGxlXCJcbiAgICAgICAgICAgICAgICAgICAgY2xhc3M9XCJzdHItY2hhdF9fbWVzc2FnZS1hdHRhY2htZW50LWZpbGUtLWl0ZW0tbmFtZVwiXG4gICAgICAgICAgICAgICAgICA+XG4gICAgICAgICAgICAgICAgICAgIHt7IGF0dGFjaG1lbnRDb250ZXh0LnRpdGxlIH19XG4gICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICAgIDxzdHJlYW0taWNvbi1wbGFjZWhvbGRlclxuICAgICAgICAgICAgICAgICAgICBjbGFzcz1cInN0ci1jaGF0X19tZXNzYWdlLWF0dGFjaG1lbnQtZG93bmxvYWQtaWNvblwiXG4gICAgICAgICAgICAgICAgICAgIGljb249XCJkb3dubG9hZFwiXG4gICAgICAgICAgICAgICAgICAvPlxuICAgICAgICAgICAgICAgIDwvYT5cbiAgICAgICAgICAgICAgICBAaWYgKGhhc0ZpbGVTaXplKGF0dGFjaG1lbnRDb250ZXh0KSkge1xuICAgICAgICAgICAgICAgICAgPHNwYW5cbiAgICAgICAgICAgICAgICAgICAgY2xhc3M9XCJzdHItY2hhdF9fbWVzc2FnZS1hdHRhY2htZW50LWZpbGUtLWl0ZW0tc2l6ZVwiXG4gICAgICAgICAgICAgICAgICAgIGRhdGEtdGVzdGNsYXNzPVwic2l6ZVwiXG4gICAgICAgICAgICAgICAgICAgID57eyBnZXRGaWxlU2l6ZShhdHRhY2htZW50Q29udGV4dCkgfX08L3NwYW5cbiAgICAgICAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgPC9uZy10ZW1wbGF0ZT5cbiAgICAgICAgfVxuICAgICAgICBAaWYgKGlzVm9pY2VNZXNzYWdlKGF0dGFjaG1lbnQpKSB7XG4gICAgICAgICAgPG5nLWNvbnRhaW5lclxuICAgICAgICAgICAgKm5nVGVtcGxhdGVPdXRsZXQ9XCJcbiAgICAgICAgICAgICAgKGN1c3RvbVRlbXBsYXRlc1NlcnZpY2Uudm9pY2VSZWNvcmRpbmdBdHRhY2htZW50VGVtcGxhdGUkXG4gICAgICAgICAgICAgICAgfCBhc3luYykgfHwgZGVmYXVsdFJlY29yZGluZztcbiAgICAgICAgICAgICAgY29udGV4dDogZ2V0QXR0YWNobWVudENvbnRleHQoYXR0YWNobWVudClcbiAgICAgICAgICAgIFwiXG4gICAgICAgICAgLz5cbiAgICAgICAgICA8bmctdGVtcGxhdGUgI2RlZmF1bHRSZWNvcmRpbmc+XG4gICAgICAgICAgICA8c3RyZWFtLXZvaWNlLXJlY29yZGluZ1xuICAgICAgICAgICAgICBkYXRhLXRlc3RjbGFzcz1cInZvaWNlLXJlY29yZGluZ1wiXG4gICAgICAgICAgICAgIFthdHRhY2htZW50XT1cImF0dGFjaG1lbnRcIlxuICAgICAgICAgICAgLz5cbiAgICAgICAgICA8L25nLXRlbXBsYXRlPlxuICAgICAgICB9XG4gICAgICAgIEBpZiAoXG4gICAgICAgICAgaXNDYXJkKGF0dGFjaG1lbnQpICYmIGdldENhcmRBdHRhY2htZW50Q29uZmlndXJhdGlvbihhdHRhY2htZW50KTtcbiAgICAgICAgICBhcyBhdHRhY2htZW50Q29uZmlndXJhdGlvblxuICAgICAgICApIHtcbiAgICAgICAgICA8bmctY29udGFpbmVyXG4gICAgICAgICAgICAqbmdUZW1wbGF0ZU91dGxldD1cIlxuICAgICAgICAgICAgICAoY3VzdG9tVGVtcGxhdGVzU2VydmljZS5jYXJkQXR0YWNobWVudFRlbXBsYXRlJCB8IGFzeW5jKSB8fFxuICAgICAgICAgICAgICAgIGRlZmF1bHRDYXJkO1xuICAgICAgICAgICAgICBjb250ZXh0OiBnZXRBdHRhY2htZW50Q29udGV4dChhdHRhY2htZW50KVxuICAgICAgICAgICAgXCJcbiAgICAgICAgICAvPlxuICAgICAgICAgIDxuZy10ZW1wbGF0ZSAjZGVmYXVsdENhcmQgbGV0LWF0dGFjaG1lbnRDb250ZXh0PVwiYXR0YWNobWVudFwiPlxuICAgICAgICAgICAgPGRpdlxuICAgICAgICAgICAgICBjbGFzcz1cInN0ci1jaGF0X19tZXNzYWdlLWF0dGFjaG1lbnQtY2FyZCBzdHItY2hhdF9fbWVzc2FnZS1hdHRhY2htZW50LWNhcmQtLXt7XG4gICAgICAgICAgICAgICAgYXR0YWNobWVudENvbnRleHQudHlwZVxuICAgICAgICAgICAgICB9fVwiXG4gICAgICAgICAgICA+XG4gICAgICAgICAgICAgIEBpZiAoYXR0YWNobWVudENvbmZpZ3VyYXRpb24udXJsKSB7XG4gICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cInN0ci1jaGF0X19tZXNzYWdlLWF0dGFjaG1lbnQtY2FyZC0taGVhZGVyXCI+XG4gICAgICAgICAgICAgICAgICBAaWYgKGF0dGFjaG1lbnRDb250ZXh0LnR5cGUgPT09IFwidmlkZW9cIikge1xuICAgICAgICAgICAgICAgICAgICA8YVxuICAgICAgICAgICAgICAgICAgICAgIFtocmVmXT1cIlxuICAgICAgICAgICAgICAgICAgICAgICAgYXR0YWNobWVudENvbnRleHQudGl0bGVfbGluayB8fFxuICAgICAgICAgICAgICAgICAgICAgICAgYXR0YWNobWVudENvbnRleHQub2dfc2NyYXBlX3VybFxuICAgICAgICAgICAgICAgICAgICAgIFwiXG4gICAgICAgICAgICAgICAgICAgICAgdGFyZ2V0PVwiX2JsYW5rXCJcbiAgICAgICAgICAgICAgICAgICAgICBkYXRhLXRlc3RjbGFzcz1cInNjcmFwZWQtdmlkZW9cIlxuICAgICAgICAgICAgICAgICAgICA+XG4gICAgICAgICAgICAgICAgICAgICAgPG5nLWNvbnRlbnQgKm5nVGVtcGxhdGVPdXRsZXQ9XCJjYXJkSW1hZ2VcIiAvPlxuICAgICAgICAgICAgICAgICAgICAgIDxkaXZcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsYXNzPVwic3RyLWNoYXRfX21lc3NhZ2UtYXR0YWNobWVudC1jYXJkLS12aWRlby1wbGF5XCJcbiAgICAgICAgICAgICAgICAgICAgICA+PC9kaXY+XG4gICAgICAgICAgICAgICAgICAgICAgPHN0cmVhbS1pY29uLXBsYWNlaG9sZGVyIGljb249XCJwbGF5XCIgLz5cbiAgICAgICAgICAgICAgICAgICAgPC9hPlxuICAgICAgICAgICAgICAgICAgfSBAZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIDxuZy1jb250ZW50ICpuZ1RlbXBsYXRlT3V0bGV0PVwiY2FyZEltYWdlXCIgLz5cbiAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgIDxuZy10ZW1wbGF0ZSAjY2FyZEltYWdlXG4gICAgICAgICAgICAgICAgICAgID48aW1nXG4gICAgICAgICAgICAgICAgICAgICAgZmV0Y2hwcmlvcml0eT1cImxvd1wiXG4gICAgICAgICAgICAgICAgICAgICAgbG9hZGluZz1cImxhenlcIlxuICAgICAgICAgICAgICAgICAgICAgIGRhdGEtdGVzdGNsYXNzPVwiY2FyZC1pbWdcIlxuICAgICAgICAgICAgICAgICAgICAgIGFsdD1cInt7IGF0dGFjaG1lbnRDb25maWd1cmF0aW9uLnVybCB9fVwiXG4gICAgICAgICAgICAgICAgICAgICAgW3NyY109XCJhdHRhY2htZW50Q29uZmlndXJhdGlvbi51cmxcIlxuICAgICAgICAgICAgICAgICAgICAgIFtuZ1N0eWxlXT1cIntcbiAgICAgICAgICAgICAgICAgICAgICAgIGhlaWdodDogYXR0YWNobWVudENvbmZpZ3VyYXRpb24uaGVpZ2h0LFxuICAgICAgICAgICAgICAgICAgICAgICAgd2lkdGg6IGF0dGFjaG1lbnRDb25maWd1cmF0aW9uLndpZHRoLFxuICAgICAgICAgICAgICAgICAgICAgIH1cIlxuICAgICAgICAgICAgICAgICAgLz48L25nLXRlbXBsYXRlPlxuICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cInN0ci1jaGF0X19tZXNzYWdlLWF0dGFjaG1lbnQtY2FyZC0tY29udGVudFwiPlxuICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJzdHItY2hhdF9fbWVzc2FnZS1hdHRhY2htZW50LWNhcmQtLWZsZXhcIj5cbiAgICAgICAgICAgICAgICAgIEBpZiAoYXR0YWNobWVudENvbnRleHQudGl0bGUpIHtcbiAgICAgICAgICAgICAgICAgICAgPGRpdlxuICAgICAgICAgICAgICAgICAgICAgIGRhdGEtdGVzdGNsYXNzPVwiY2FyZC10aXRsZVwiXG4gICAgICAgICAgICAgICAgICAgICAgY2xhc3M9XCJzdHItY2hhdF9fbWVzc2FnZS1hdHRhY2htZW50LWNhcmQtLXRpdGxlXCJcbiAgICAgICAgICAgICAgICAgICAgPlxuICAgICAgICAgICAgICAgICAgICAgIHt7IGF0dGFjaG1lbnRDb250ZXh0LnRpdGxlIH19XG4gICAgICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgQGlmIChhdHRhY2htZW50Q29udGV4dC50ZXh0KSB7XG4gICAgICAgICAgICAgICAgICAgIDxkaXZcbiAgICAgICAgICAgICAgICAgICAgICBjbGFzcz1cInN0ci1jaGF0X19tZXNzYWdlLWF0dGFjaG1lbnQtY2FyZC0tdGV4dFwiXG4gICAgICAgICAgICAgICAgICAgICAgZGF0YS10ZXN0Y2xhc3M9XCJjYXJkLXRleHRcIlxuICAgICAgICAgICAgICAgICAgICA+XG4gICAgICAgICAgICAgICAgICAgICAge3sgYXR0YWNobWVudENvbnRleHQudGV4dCB9fVxuICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgIEBpZiAoXG4gICAgICAgICAgICAgICAgICAgIGF0dGFjaG1lbnRDb250ZXh0LnRpdGxlX2xpbmsgfHxcbiAgICAgICAgICAgICAgICAgICAgYXR0YWNobWVudENvbnRleHQub2dfc2NyYXBlX3VybFxuICAgICAgICAgICAgICAgICAgKSB7XG4gICAgICAgICAgICAgICAgICAgIDxhXG4gICAgICAgICAgICAgICAgICAgICAgY2xhc3M9XCJzdHItY2hhdF9fbWVzc2FnZS1hdHRhY2htZW50LWNhcmQtLXVybFwiXG4gICAgICAgICAgICAgICAgICAgICAgZGF0YS10ZXN0Y2xhc3M9XCJ1cmwtbGlua1wiXG4gICAgICAgICAgICAgICAgICAgICAgbm9vcGVuZXJcbiAgICAgICAgICAgICAgICAgICAgICBub3JlZmVycmVyXG4gICAgICAgICAgICAgICAgICAgICAgdGFyZ2V0PVwiX2JsYW5rXCJcbiAgICAgICAgICAgICAgICAgICAgICBocmVmPVwie3tcbiAgICAgICAgICAgICAgICAgICAgICAgIGF0dGFjaG1lbnRDb250ZXh0LnRpdGxlX2xpbmsgfHxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgYXR0YWNobWVudENvbnRleHQub2dfc2NyYXBlX3VybFxuICAgICAgICAgICAgICAgICAgICAgIH19XCJcbiAgICAgICAgICAgICAgICAgICAgPlxuICAgICAgICAgICAgICAgICAgICAgIHt7XG4gICAgICAgICAgICAgICAgICAgICAgICB0cmltVXJsKFxuICAgICAgICAgICAgICAgICAgICAgICAgICBhdHRhY2htZW50Q29udGV4dC50aXRsZV9saW5rIHx8XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYXR0YWNobWVudENvbnRleHQub2dfc2NyYXBlX3VybFxuICAgICAgICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgICAgICAgIH19XG4gICAgICAgICAgICAgICAgICAgIDwvYT5cbiAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICA8L25nLXRlbXBsYXRlPlxuICAgICAgICB9XG4gICAgICAgIEBpZiAoYXR0YWNobWVudC5hY3Rpb25zICYmIGF0dGFjaG1lbnQuYWN0aW9ucy5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgPG5nLWNvbnRhaW5lclxuICAgICAgICAgICAgKm5nVGVtcGxhdGVPdXRsZXQ9XCJcbiAgICAgICAgICAgICAgKGN1c3RvbVRlbXBsYXRlc1NlcnZpY2UuYXR0YWNobWVudEFjdGlvbnNUZW1wbGF0ZSQgfCBhc3luYykgfHxcbiAgICAgICAgICAgICAgICBkZWZhdWx0QWN0aW9ucztcbiAgICAgICAgICAgICAgY29udGV4dDogZ2V0QXR0YWNobWVudENvbnRleHQoYXR0YWNobWVudClcbiAgICAgICAgICAgIFwiXG4gICAgICAgICAgLz5cbiAgICAgICAgICA8bmctdGVtcGxhdGUgI2RlZmF1bHRBY3Rpb25zIGxldC1hdHRhY2htZW50Q29udGV4dD1cImF0dGFjaG1lbnRcIj5cbiAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJzdHItY2hhdF9fbWVzc2FnZS1hdHRhY2htZW50LWFjdGlvbnNcIj5cbiAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cInN0ci1jaGF0X19tZXNzYWdlLWF0dGFjaG1lbnQtYWN0aW9ucy1mb3JtXCI+XG4gICAgICAgICAgICAgICAgQGZvciAoYWN0aW9uIG9mIGF0dGFjaG1lbnRDb250ZXh0LmFjdGlvbnM7IHRyYWNrIGFjdGlvbi52YWx1ZSkge1xuICAgICAgICAgICAgICAgICAgPGJ1dHRvblxuICAgICAgICAgICAgICAgICAgICBkYXRhLXRlc3RjbGFzcz1cImF0dGFjaG1lbnQtYWN0aW9uXCJcbiAgICAgICAgICAgICAgICAgICAgY2xhc3M9XCJzdHItY2hhdF9fbWVzc2FnZS1hdHRhY2htZW50LWFjdGlvbnMtYnV0dG9uIHN0ci1jaGF0X19tZXNzYWdlLWF0dGFjaG1lbnQtYWN0aW9ucy1idXR0b24tLXt7XG4gICAgICAgICAgICAgICAgICAgICAgYWN0aW9uLnN0eWxlXG4gICAgICAgICAgICAgICAgICAgIH19XCJcbiAgICAgICAgICAgICAgICAgICAgKGNsaWNrKT1cInNlbmRBY3Rpb24oYWN0aW9uKVwiXG4gICAgICAgICAgICAgICAgICAgIChrZXl1cC5lbnRlcik9XCJzZW5kQWN0aW9uKGFjdGlvbilcIlxuICAgICAgICAgICAgICAgICAgPlxuICAgICAgICAgICAgICAgICAgICB7eyBhY3Rpb24udGV4dCB9fVxuICAgICAgICAgICAgICAgICAgPC9idXR0b24+XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgIDwvbmctdGVtcGxhdGU+XG4gICAgICAgIH1cbiAgICAgIDwvZGl2PlxuICAgIH1cbiAgICBAaWYgKGN1c3RvbUF0dGFjaG1lbnRzVGVtcGxhdGUpIHtcbiAgICAgIDxuZy10ZW1wbGF0ZVxuICAgICAgICAqbmdUZW1wbGF0ZU91dGxldD1cIlxuICAgICAgICAgIGN1c3RvbUF0dGFjaG1lbnRzVGVtcGxhdGU7XG4gICAgICAgICAgY29udGV4dDoge1xuICAgICAgICAgICAgbWVzc2FnZUlkOiBtZXNzYWdlSWQhLFxuICAgICAgICAgICAgcGFyZW50TWVzc2FnZUlkOiBwYXJlbnRNZXNzYWdlSWQsXG4gICAgICAgICAgICBhdHRhY2htZW50czogY3VzdG9tQXR0YWNobWVudHMsXG4gICAgICAgICAgfVxuICAgICAgICBcIlxuICAgICAgLz5cbiAgICB9XG5cbiAgICBAaWYgKGltYWdlc1RvVmlldyAmJiBpbWFnZXNUb1ZpZXcubGVuZ3RoID4gMCkge1xuICAgICAgPG5nLWNvbnRhaW5lclxuICAgICAgICAqbmdUZW1wbGF0ZU91dGxldD1cIlxuICAgICAgICAgIChjdXN0b21UZW1wbGF0ZXNTZXJ2aWNlLm1vZGFsVGVtcGxhdGUkIHwgYXN5bmMpIHx8IGRlZmF1bHRNb2RhbDtcbiAgICAgICAgICBjb250ZXh0OiBnZXRNb2RhbENvbnRleHQoKVxuICAgICAgICBcIlxuICAgICAgLz5cbiAgICB9XG4gIDwvZGl2PlxufVxuXG48bmctdGVtcGxhdGVcbiAgI2RlZmF1bHRNb2RhbFxuICBsZXQtaXNPcGVuPVwiaXNPcGVuXCJcbiAgbGV0LWlzT3BlbkNoYW5nZUhhbmRsZXI9XCJpc09wZW5DaGFuZ2VIYW5kbGVyXCJcbiAgbGV0LWNvbnRlbnQ9XCJjb250ZW50XCJcbj5cbiAgPHN0cmVhbS1tb2RhbFxuICAgIGNsYXNzPVwic3RyZWFtLWNoYXQtYW5ndWxhcl9faW1hZ2UtbW9kYWwtaG9zdFwiXG4gICAgW2lzT3Blbl09XCJpc09wZW5cIlxuICAgIFtjb250ZW50XT1cImNvbnRlbnRcIlxuICAgIChpc09wZW5DaGFuZ2UpPVwiaXNPcGVuQ2hhbmdlSGFuZGxlcigkZXZlbnQpXCJcbiAgLz5cbjwvbmctdGVtcGxhdGU+XG5cbjxuZy10ZW1wbGF0ZSAjbW9kYWxDb250ZW50PlxuICA8ZGl2IGNsYXNzPVwic3RyZWFtLWNoYXQtYW5ndWxhcl9faW1hZ2UtbW9kYWwgc3RyLWNoYXRfX2ltYWdlLWNhcm91c2VsXCI+XG4gICAgPGltZ1xuICAgICAgI2ltZ0VsZW1lbnRcbiAgICAgIGNsYXNzPVwic3RyZWFtLWNoYXQtYW5ndWxhcl9faW1hZ2UtbW9kYWwtaW1hZ2Ugc3RyLWNoYXRfX2ltYWdlLWNhcm91c2VsLWltYWdlXCJcbiAgICAgIGRhdGEtdGVzdGlkPVwibW9kYWwtaW1hZ2VcIlxuICAgICAgW3NyY109XCJcbiAgICAgICAgZ2V0Q2Fyb3VzZWxJbWFnZUF0dGFjaG1lbnRDb25maWd1cmF0aW9uKFxuICAgICAgICAgIGltYWdlc1RvVmlld1tpbWFnZXNUb1ZpZXdDdXJyZW50SW5kZXhdLFxuICAgICAgICAgIGltZ0VsZW1lbnRcbiAgICAgICAgKS51cmxcbiAgICAgIFwiXG4gICAgICBbc3R5bGUuLS1vcmlnaW5hbC1oZWlnaHRdPVwiXG4gICAgICAgIGdldENhcm91c2VsSW1hZ2VBdHRhY2htZW50Q29uZmlndXJhdGlvbihcbiAgICAgICAgICBpbWFnZXNUb1ZpZXdbaW1hZ2VzVG9WaWV3Q3VycmVudEluZGV4XSxcbiAgICAgICAgICBpbWdFbGVtZW50XG4gICAgICAgICkub3JpZ2luYWxIZWlnaHRcbiAgICAgIFwiXG4gICAgICBbc3R5bGUuLS1vcmlnaW5hbC13aWR0aF09XCJcbiAgICAgICAgZ2V0Q2Fyb3VzZWxJbWFnZUF0dGFjaG1lbnRDb25maWd1cmF0aW9uKFxuICAgICAgICAgIGltYWdlc1RvVmlld1tpbWFnZXNUb1ZpZXdDdXJyZW50SW5kZXhdLFxuICAgICAgICAgIGltZ0VsZW1lbnRcbiAgICAgICAgKS5vcmlnaW5hbFdpZHRoXG4gICAgICBcIlxuICAgICAgW2FsdF09XCJpbWFnZXNUb1ZpZXdbaW1hZ2VzVG9WaWV3Q3VycmVudEluZGV4XS5mYWxsYmFja1wiXG4gICAgICBbbmdTdHlsZV09XCJ7XG4gICAgICAgIHdpZHRoOiBnZXRDYXJvdXNlbEltYWdlQXR0YWNobWVudENvbmZpZ3VyYXRpb24oXG4gICAgICAgICAgaW1hZ2VzVG9WaWV3W2ltYWdlc1RvVmlld0N1cnJlbnRJbmRleF0sXG4gICAgICAgICAgaW1nRWxlbWVudFxuICAgICAgICApLndpZHRoLFxuICAgICAgICBoZWlnaHQ6IGdldENhcm91c2VsSW1hZ2VBdHRhY2htZW50Q29uZmlndXJhdGlvbihcbiAgICAgICAgICBpbWFnZXNUb1ZpZXdbaW1hZ2VzVG9WaWV3Q3VycmVudEluZGV4XSxcbiAgICAgICAgICBpbWdFbGVtZW50XG4gICAgICAgICkuaGVpZ2h0LFxuICAgICAgfVwiXG4gICAgLz5cbiAgICA8ZGl2PlxuICAgICAgPGJ1dHRvblxuICAgICAgICBjbGFzcz1cInN0cmVhbS1jaGF0LWFuZ3VsYXJfX2ltYWdlLW1vZGFsLXN0ZXBwZXIgc3RyLWNoYXRfX2ltYWdlLWNhcm91c2VsLXN0ZXBwZXIgc3RyLWNoYXRfX2ltYWdlLWNhcm91c2VsLXN0ZXBwZXItcHJldlwiXG4gICAgICAgIGRhdGEtdGVzdGlkPVwiaW1hZ2UtbW9kYWwtcHJldlwiXG4gICAgICAgIHR5cGU9XCJidXR0b25cIlxuICAgICAgICBbbmdTdHlsZV09XCJ7XG4gICAgICAgICAgdmlzaWJpbGl0eTogaXNJbWFnZU1vZGFsUHJldkJ1dHRvblZpc2libGUgPyAndmlzaWJsZScgOiAnaGlkZGVuJyxcbiAgICAgICAgfVwiXG4gICAgICAgIChjbGljayk9XCJzdGVwSW1hZ2VzKC0xKVwiXG4gICAgICAgIChrZXl1cC5lbnRlcik9XCJzdGVwSW1hZ2VzKC0xKVwiXG4gICAgICA+XG4gICAgICAgIDxzdHJlYW0taWNvbi1wbGFjZWhvbGRlciBpY29uPVwiYXJyb3ctbGVmdFwiIC8+XG4gICAgICA8L2J1dHRvbj5cbiAgICAgIDxidXR0b25cbiAgICAgICAgY2xhc3M9XCJzdHJlYW0tY2hhdC1hbmd1bGFyX19pbWFnZS1tb2RhbC1zdGVwcGVyIHN0ci1jaGF0X19pbWFnZS1jYXJvdXNlbC1zdGVwcGVyIHN0ci1jaGF0X19pbWFnZS1jYXJvdXNlbC1zdGVwcGVyLW5leHRcIlxuICAgICAgICB0eXBlPVwiYnV0dG9uXCJcbiAgICAgICAgZGF0YS10ZXN0aWQ9XCJpbWFnZS1tb2RhbC1uZXh0XCJcbiAgICAgICAgW25nU3R5bGVdPVwie1xuICAgICAgICAgIHZpc2liaWxpdHk6IGlzSW1hZ2VNb2RhbE5leHRCdXR0b25WaXNpYmxlID8gJ3Zpc2libGUnIDogJ2hpZGRlbicsXG4gICAgICAgIH1cIlxuICAgICAgICAoY2xpY2spPVwic3RlcEltYWdlcygxKVwiXG4gICAgICAgIChrZXl1cC5lbnRlcik9XCJzdGVwSW1hZ2VzKDEpXCJcbiAgICAgID5cbiAgICAgICAgPHN0cmVhbS1pY29uLXBsYWNlaG9sZGVyIGljb249XCJhcnJvdy1yaWdodFwiIC8+XG4gICAgICA8L2J1dHRvbj5cbiAgICA8L2Rpdj5cbiAgPC9kaXY+XG48L25nLXRlbXBsYXRlPlxuIl19
@@ -0,0 +1,55 @@
1
+ import { Component, EventEmitter, Input, Output, } from '@angular/core';
2
+ import * as i0 from "@angular/core";
3
+ import * as i1 from "../custom-templates.service";
4
+ import * as i2 from "../attachment.service";
5
+ import * as i3 from "@angular/common";
6
+ import * as i4 from "../icon/icon-placeholder/icon-placeholder.component";
7
+ import * as i5 from "../icon/loading-indicator-placeholder/loading-indicator-placeholder.component";
8
+ /**
9
+ * The `AttachmentPreviewList` component displays a preview of the attachments uploaded to a message. Users can delete attachments using the preview component, or retry upload if it failed previously.
10
+ */
11
+ export class AttachmentPreviewListComponent {
12
+ constructor(customTemplateService, attachmentService) {
13
+ this.customTemplateService = customTemplateService;
14
+ this.attachmentService = attachmentService;
15
+ /**
16
+ * An output to notify the parent component if the user tries to retry a failed upload
17
+ */
18
+ this.retryAttachmentUpload = new EventEmitter();
19
+ /**
20
+ * An output to notify the parent component if the user wants to delete a file
21
+ */
22
+ this.deleteAttachment = new EventEmitter();
23
+ this.customAttachments = [];
24
+ this.subscriptions = [];
25
+ }
26
+ ngOnInit() {
27
+ this.subscriptions.push(this.customTemplateService.customAttachmentPreviewListTemplate$.subscribe((t) => (this.customAttachmentsPreview = t)));
28
+ this.subscriptions.push(this.attachmentService.customAttachments$.subscribe((a) => (this.customAttachments = a)));
29
+ }
30
+ ngOnDestroy() {
31
+ this.subscriptions.forEach((s) => s.unsubscribe());
32
+ }
33
+ attachmentUploadRetried(file) {
34
+ this.retryAttachmentUpload.emit(file);
35
+ }
36
+ attachmentDeleted(upload) {
37
+ this.deleteAttachment.emit(upload);
38
+ }
39
+ trackByFile(_, item) {
40
+ return item.file;
41
+ }
42
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.0", ngImport: i0, type: AttachmentPreviewListComponent, deps: [{ token: i1.CustomTemplatesService }, { token: i2.AttachmentService }], target: i0.ɵɵFactoryTarget.Component }); }
43
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.0.0", type: AttachmentPreviewListComponent, selector: "stream-attachment-preview-list", inputs: { attachmentUploads$: "attachmentUploads$" }, outputs: { retryAttachmentUpload: "retryAttachmentUpload", deleteAttachment: "deleteAttachment" }, ngImport: i0, template: "@if (\n (attachmentUploads$ | async)?.length ||\n (customAttachments.length > 0 && customAttachmentsPreview)\n) {\n <div class=\"str-chat__attachment-preview-list\">\n <div class=\"str-chat__attachment-list-scroll-container\">\n @for (\n attachmentUpload of attachmentUploads$ | async;\n track attachmentUpload.file\n ) {\n @if (attachmentUpload.type === \"image\") {\n <div\n class=\"str-chat__attachment-preview-image\"\n data-testclass=\"attachment-image-preview\"\n >\n <ng-container\n *ngTemplateOutlet=\"\n deleteButton;\n context: { attachmentUpload: attachmentUpload }\n \"\n />\n @if (attachmentUpload.state === \"uploading\") {\n <div class=\"str-chat__attachment-preview-image-loading\">\n <stream-loading-indicator-placeholder\n data-testclass=\"loading-indicator\"\n />\n </div>\n }\n <ng-container\n *ngTemplateOutlet=\"\n retryButton;\n context: { attachmentUpload: attachmentUpload }\n \"\n />\n @if (attachmentUpload.url || attachmentUpload.previewUri) {\n <img\n class=\"str-chat__attachment-preview-thumbnail\"\n data-testclass=\"attachment-image\"\n src=\"{{\n attachmentUpload.url\n ? attachmentUpload.url\n : attachmentUpload.previewUri\n }}\"\n alt=\"{{ attachmentUpload.file.name }}\"\n />\n }\n </div>\n }\n @if (\n attachmentUpload.type === \"file\" ||\n attachmentUpload.type === \"video\" ||\n attachmentUpload.type === \"voiceRecording\"\n ) {\n <div\n class=\"str-chat__attachment-preview-file str-chat__attachment-preview-type-{{\n attachmentUpload.type\n }}\"\n data-testclass=\"attachment-file-preview\"\n >\n <stream-icon-placeholder\n class=\"str-chat__attachment-preview-file-icon\"\n icon=\"unspecified-filetype\"\n />\n <div class=\"str-chat__attachment-preview-file-end\">\n <div\n class=\"str-chat__attachment-preview-file-name\"\n title=\"{{ attachmentUpload.file.name }}\"\n >\n {{ attachmentUpload.file.name }}\n </div>\n @if (attachmentUpload.state === \"success\") {\n <a\n class=\"str-chat__attachment-preview-file-download\"\n data-testclass=\"file-download-link\"\n download\n href=\"{{ attachmentUpload.url }}\"\n (click)=\"\n attachmentUpload.url ? null : $event.preventDefault()\n \"\n (keyup.enter)=\"\n attachmentUpload.url ? null : $event.preventDefault()\n \"\n >\n <stream-icon-placeholder icon=\"download\" />\n </a>\n }\n @if (attachmentUpload.state === \"uploading\") {\n <stream-loading-indicator-placeholder\n data-testclass=\"loading-indicator\"\n />\n }\n </div>\n <ng-container\n *ngTemplateOutlet=\"\n deleteButton;\n context: { attachmentUpload: attachmentUpload }\n \"\n />\n <ng-container\n *ngTemplateOutlet=\"\n retryButton;\n context: { attachmentUpload: attachmentUpload }\n \"\n />\n </div>\n }\n }\n @if (customAttachmentsPreview) {\n <ng-template\n *ngTemplateOutlet=\"\n customAttachmentsPreview;\n context: { service: attachmentService }\n \"\n />\n }\n </div>\n </div>\n}\n\n<ng-template #deleteButton let-attachmentUpload=\"attachmentUpload\">\n <div\n class=\"str-chat__attachment-preview-delete\"\n data-testclass=\"file-delete\"\n role=\"button\"\n (click)=\"attachmentDeleted(attachmentUpload)\"\n (keyup.enter)=\"attachmentDeleted(attachmentUpload)\"\n >\n <stream-icon-placeholder icon=\"close\" />\n </div>\n</ng-template>\n\n<ng-template #retryButton let-attachmentUpload=\"attachmentUpload\">\n @if (attachmentUpload.state === \"error\") {\n <div\n data-testclass=\"upload-retry\"\n class=\"str-chat__attachment-preview-error str-chat__attachment-preview-error-{{\n attachmentUpload.type === 'image' ? 'image' : 'file'\n }}\"\n (click)=\"attachmentUploadRetried(attachmentUpload.file)\"\n (keyup.enter)=\"attachmentUploadRetried(attachmentUpload.file)\"\n >\n <stream-icon-placeholder icon=\"retry\" />\n </div>\n }\n</ng-template>\n", dependencies: [{ kind: "directive", type: i3.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: i4.IconPlaceholderComponent, selector: "stream-icon-placeholder", inputs: ["icon"] }, { kind: "component", type: i5.LoadingIndicatorPlaceholderComponent, selector: "stream-loading-indicator-placeholder" }, { kind: "pipe", type: i3.AsyncPipe, name: "async" }] }); }
44
+ }
45
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.0", ngImport: i0, type: AttachmentPreviewListComponent, decorators: [{
46
+ type: Component,
47
+ args: [{ selector: 'stream-attachment-preview-list', template: "@if (\n (attachmentUploads$ | async)?.length ||\n (customAttachments.length > 0 && customAttachmentsPreview)\n) {\n <div class=\"str-chat__attachment-preview-list\">\n <div class=\"str-chat__attachment-list-scroll-container\">\n @for (\n attachmentUpload of attachmentUploads$ | async;\n track attachmentUpload.file\n ) {\n @if (attachmentUpload.type === \"image\") {\n <div\n class=\"str-chat__attachment-preview-image\"\n data-testclass=\"attachment-image-preview\"\n >\n <ng-container\n *ngTemplateOutlet=\"\n deleteButton;\n context: { attachmentUpload: attachmentUpload }\n \"\n />\n @if (attachmentUpload.state === \"uploading\") {\n <div class=\"str-chat__attachment-preview-image-loading\">\n <stream-loading-indicator-placeholder\n data-testclass=\"loading-indicator\"\n />\n </div>\n }\n <ng-container\n *ngTemplateOutlet=\"\n retryButton;\n context: { attachmentUpload: attachmentUpload }\n \"\n />\n @if (attachmentUpload.url || attachmentUpload.previewUri) {\n <img\n class=\"str-chat__attachment-preview-thumbnail\"\n data-testclass=\"attachment-image\"\n src=\"{{\n attachmentUpload.url\n ? attachmentUpload.url\n : attachmentUpload.previewUri\n }}\"\n alt=\"{{ attachmentUpload.file.name }}\"\n />\n }\n </div>\n }\n @if (\n attachmentUpload.type === \"file\" ||\n attachmentUpload.type === \"video\" ||\n attachmentUpload.type === \"voiceRecording\"\n ) {\n <div\n class=\"str-chat__attachment-preview-file str-chat__attachment-preview-type-{{\n attachmentUpload.type\n }}\"\n data-testclass=\"attachment-file-preview\"\n >\n <stream-icon-placeholder\n class=\"str-chat__attachment-preview-file-icon\"\n icon=\"unspecified-filetype\"\n />\n <div class=\"str-chat__attachment-preview-file-end\">\n <div\n class=\"str-chat__attachment-preview-file-name\"\n title=\"{{ attachmentUpload.file.name }}\"\n >\n {{ attachmentUpload.file.name }}\n </div>\n @if (attachmentUpload.state === \"success\") {\n <a\n class=\"str-chat__attachment-preview-file-download\"\n data-testclass=\"file-download-link\"\n download\n href=\"{{ attachmentUpload.url }}\"\n (click)=\"\n attachmentUpload.url ? null : $event.preventDefault()\n \"\n (keyup.enter)=\"\n attachmentUpload.url ? null : $event.preventDefault()\n \"\n >\n <stream-icon-placeholder icon=\"download\" />\n </a>\n }\n @if (attachmentUpload.state === \"uploading\") {\n <stream-loading-indicator-placeholder\n data-testclass=\"loading-indicator\"\n />\n }\n </div>\n <ng-container\n *ngTemplateOutlet=\"\n deleteButton;\n context: { attachmentUpload: attachmentUpload }\n \"\n />\n <ng-container\n *ngTemplateOutlet=\"\n retryButton;\n context: { attachmentUpload: attachmentUpload }\n \"\n />\n </div>\n }\n }\n @if (customAttachmentsPreview) {\n <ng-template\n *ngTemplateOutlet=\"\n customAttachmentsPreview;\n context: { service: attachmentService }\n \"\n />\n }\n </div>\n </div>\n}\n\n<ng-template #deleteButton let-attachmentUpload=\"attachmentUpload\">\n <div\n class=\"str-chat__attachment-preview-delete\"\n data-testclass=\"file-delete\"\n role=\"button\"\n (click)=\"attachmentDeleted(attachmentUpload)\"\n (keyup.enter)=\"attachmentDeleted(attachmentUpload)\"\n >\n <stream-icon-placeholder icon=\"close\" />\n </div>\n</ng-template>\n\n<ng-template #retryButton let-attachmentUpload=\"attachmentUpload\">\n @if (attachmentUpload.state === \"error\") {\n <div\n data-testclass=\"upload-retry\"\n class=\"str-chat__attachment-preview-error str-chat__attachment-preview-error-{{\n attachmentUpload.type === 'image' ? 'image' : 'file'\n }}\"\n (click)=\"attachmentUploadRetried(attachmentUpload.file)\"\n (keyup.enter)=\"attachmentUploadRetried(attachmentUpload.file)\"\n >\n <stream-icon-placeholder icon=\"retry\" />\n </div>\n }\n</ng-template>\n" }]
48
+ }], ctorParameters: () => [{ type: i1.CustomTemplatesService }, { type: i2.AttachmentService }], propDecorators: { attachmentUploads$: [{
49
+ type: Input
50
+ }], retryAttachmentUpload: [{
51
+ type: Output
52
+ }], deleteAttachment: [{
53
+ type: Output
54
+ }] } });
55
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXR0YWNobWVudC1wcmV2aWV3LWxpc3QuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvc3RyZWFtLWNoYXQtYW5ndWxhci9zcmMvbGliL2F0dGFjaG1lbnQtcHJldmlldy1saXN0L2F0dGFjaG1lbnQtcHJldmlldy1saXN0LmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL3N0cmVhbS1jaGF0LWFuZ3VsYXIvc3JjL2xpYi9hdHRhY2htZW50LXByZXZpZXctbGlzdC9hdHRhY2htZW50LXByZXZpZXctbGlzdC5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQ0wsU0FBUyxFQUNULFlBQVksRUFDWixLQUFLLEVBR0wsTUFBTSxHQUVQLE1BQU0sZUFBZSxDQUFDOzs7Ozs7O0FBT3ZCOztHQUVHO0FBTUgsTUFBTSxPQUFPLDhCQUE4QjtJQWlCekMsWUFDVSxxQkFBNkMsRUFDckMsaUJBQW9DO1FBRDVDLDBCQUFxQixHQUFyQixxQkFBcUIsQ0FBd0I7UUFDckMsc0JBQWlCLEdBQWpCLGlCQUFpQixDQUFtQjtRQWR0RDs7V0FFRztRQUNnQiwwQkFBcUIsR0FBRyxJQUFJLFlBQVksRUFBUSxDQUFDO1FBQ3BFOztXQUVHO1FBQ2dCLHFCQUFnQixHQUFHLElBQUksWUFBWSxFQUFvQixDQUFDO1FBQzNFLHNCQUFpQixHQUFpQixFQUFFLENBQUM7UUFFN0Isa0JBQWEsR0FBbUIsRUFBRSxDQUFDO0lBS3hDLENBQUM7SUFFSixRQUFRO1FBQ04sSUFBSSxDQUFDLGFBQWEsQ0FBQyxJQUFJLENBQ3JCLElBQUksQ0FBQyxxQkFBcUIsQ0FBQyxvQ0FBb0MsQ0FBQyxTQUFTLENBQ3ZFLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLElBQUksQ0FBQyx3QkFBd0IsR0FBRyxDQUFDLENBQUMsQ0FDM0MsQ0FDRixDQUFDO1FBQ0YsSUFBSSxDQUFDLGFBQWEsQ0FBQyxJQUFJLENBQ3JCLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxrQkFBa0IsQ0FBQyxTQUFTLENBQ2pELENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLElBQUksQ0FBQyxpQkFBaUIsR0FBRyxDQUFDLENBQUMsQ0FDcEMsQ0FDRixDQUFDO0lBQ0osQ0FBQztJQUVELFdBQVc7UUFDVCxJQUFJLENBQUMsYUFBYSxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLFdBQVcsRUFBRSxDQUFDLENBQUM7SUFDckQsQ0FBQztJQUVELHVCQUF1QixDQUFDLElBQVU7UUFDaEMsSUFBSSxDQUFDLHFCQUFxQixDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUN4QyxDQUFDO0lBRUQsaUJBQWlCLENBQUMsTUFBd0I7UUFDeEMsSUFBSSxDQUFDLGdCQUFnQixDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUNyQyxDQUFDO0lBRUQsV0FBVyxDQUFDLENBQVMsRUFBRSxJQUFzQjtRQUMzQyxPQUFPLElBQUksQ0FBQyxJQUFJLENBQUM7SUFDbkIsQ0FBQzs4R0FqRFUsOEJBQThCO2tHQUE5Qiw4QkFBOEIsK05DdkIzQyxpaUtBaUpBOzsyRkQxSGEsOEJBQThCO2tCQUwxQyxTQUFTOytCQUNFLGdDQUFnQzsySEFRakMsa0JBQWtCO3NCQUExQixLQUFLO2dCQUlhLHFCQUFxQjtzQkFBdkMsTUFBTTtnQkFJWSxnQkFBZ0I7c0JBQWxDLE1BQU0iLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xuICBDb21wb25lbnQsXG4gIEV2ZW50RW1pdHRlcixcbiAgSW5wdXQsXG4gIE9uRGVzdHJveSxcbiAgT25Jbml0LFxuICBPdXRwdXQsXG4gIFRlbXBsYXRlUmVmLFxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IE9ic2VydmFibGUsIFN1YnNjcmlwdGlvbiB9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHsgQXR0YWNobWVudFVwbG9hZCwgQ3VzdG9tQXR0YWNobWVudFByZXZpZXdMaXN0Q29udGV4dCB9IGZyb20gJy4uL3R5cGVzJztcbmltcG9ydCB7IEN1c3RvbVRlbXBsYXRlc1NlcnZpY2UgfSBmcm9tICcuLi9jdXN0b20tdGVtcGxhdGVzLnNlcnZpY2UnO1xuaW1wb3J0IHsgQXR0YWNobWVudFNlcnZpY2UgfSBmcm9tICcuLi9hdHRhY2htZW50LnNlcnZpY2UnO1xuaW1wb3J0IHsgQXR0YWNobWVudCB9IGZyb20gJ3N0cmVhbS1jaGF0JztcblxuLyoqXG4gKiBUaGUgYEF0dGFjaG1lbnRQcmV2aWV3TGlzdGAgY29tcG9uZW50IGRpc3BsYXlzIGEgcHJldmlldyBvZiB0aGUgYXR0YWNobWVudHMgdXBsb2FkZWQgdG8gYSBtZXNzYWdlLiBVc2VycyBjYW4gZGVsZXRlIGF0dGFjaG1lbnRzIHVzaW5nIHRoZSBwcmV2aWV3IGNvbXBvbmVudCwgb3IgcmV0cnkgdXBsb2FkIGlmIGl0IGZhaWxlZCBwcmV2aW91c2x5LlxuICovXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICdzdHJlYW0tYXR0YWNobWVudC1wcmV2aWV3LWxpc3QnLFxuICB0ZW1wbGF0ZVVybDogJy4vYXR0YWNobWVudC1wcmV2aWV3LWxpc3QuY29tcG9uZW50Lmh0bWwnLFxuICBzdHlsZXM6IFtdLFxufSlcbmV4cG9ydCBjbGFzcyBBdHRhY2htZW50UHJldmlld0xpc3RDb21wb25lbnQgaW1wbGVtZW50cyBPbkluaXQsIE9uRGVzdHJveSB7XG4gIC8qKlxuICAgKiBBIHN0cmVhbSB0aGF0IGVtaXRzIHRoZSBjdXJyZW50IGZpbGUgdXBsb2FkcyBhbmQgdGhlaXIgc3RhdGVzXG4gICAqL1xuICBASW5wdXQoKSBhdHRhY2htZW50VXBsb2FkcyQ6IE9ic2VydmFibGU8QXR0YWNobWVudFVwbG9hZFtdPiB8IHVuZGVmaW5lZDtcbiAgLyoqXG4gICAqIEFuIG91dHB1dCB0byBub3RpZnkgdGhlIHBhcmVudCBjb21wb25lbnQgaWYgdGhlIHVzZXIgdHJpZXMgdG8gcmV0cnkgYSBmYWlsZWQgdXBsb2FkXG4gICAqL1xuICBAT3V0cHV0KCkgcmVhZG9ubHkgcmV0cnlBdHRhY2htZW50VXBsb2FkID0gbmV3IEV2ZW50RW1pdHRlcjxGaWxlPigpO1xuICAvKipcbiAgICogQW4gb3V0cHV0IHRvIG5vdGlmeSB0aGUgcGFyZW50IGNvbXBvbmVudCBpZiB0aGUgdXNlciB3YW50cyB0byBkZWxldGUgYSBmaWxlXG4gICAqL1xuICBAT3V0cHV0KCkgcmVhZG9ubHkgZGVsZXRlQXR0YWNobWVudCA9IG5ldyBFdmVudEVtaXR0ZXI8QXR0YWNobWVudFVwbG9hZD4oKTtcbiAgY3VzdG9tQXR0YWNobWVudHM6IEF0dGFjaG1lbnRbXSA9IFtdO1xuICBjdXN0b21BdHRhY2htZW50c1ByZXZpZXc/OiBUZW1wbGF0ZVJlZjxDdXN0b21BdHRhY2htZW50UHJldmlld0xpc3RDb250ZXh0PjtcbiAgcHJpdmF0ZSBzdWJzY3JpcHRpb25zOiBTdWJzY3JpcHRpb25bXSA9IFtdO1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHByaXZhdGUgY3VzdG9tVGVtcGxhdGVTZXJ2aWNlOiBDdXN0b21UZW1wbGF0ZXNTZXJ2aWNlLFxuICAgIHB1YmxpYyByZWFkb25seSBhdHRhY2htZW50U2VydmljZTogQXR0YWNobWVudFNlcnZpY2UsXG4gICkge31cblxuICBuZ09uSW5pdCgpOiB2b2lkIHtcbiAgICB0aGlzLnN1YnNjcmlwdGlvbnMucHVzaChcbiAgICAgIHRoaXMuY3VzdG9tVGVtcGxhdGVTZXJ2aWNlLmN1c3RvbUF0dGFjaG1lbnRQcmV2aWV3TGlzdFRlbXBsYXRlJC5zdWJzY3JpYmUoXG4gICAgICAgICh0KSA9PiAodGhpcy5jdXN0b21BdHRhY2htZW50c1ByZXZpZXcgPSB0KSxcbiAgICAgICksXG4gICAgKTtcbiAgICB0aGlzLnN1YnNjcmlwdGlvbnMucHVzaChcbiAgICAgIHRoaXMuYXR0YWNobWVudFNlcnZpY2UuY3VzdG9tQXR0YWNobWVudHMkLnN1YnNjcmliZShcbiAgICAgICAgKGEpID0+ICh0aGlzLmN1c3RvbUF0dGFjaG1lbnRzID0gYSksXG4gICAgICApLFxuICAgICk7XG4gIH1cblxuICBuZ09uRGVzdHJveSgpOiB2b2lkIHtcbiAgICB0aGlzLnN1YnNjcmlwdGlvbnMuZm9yRWFjaCgocykgPT4gcy51bnN1YnNjcmliZSgpKTtcbiAgfVxuXG4gIGF0dGFjaG1lbnRVcGxvYWRSZXRyaWVkKGZpbGU6IEZpbGUpIHtcbiAgICB0aGlzLnJldHJ5QXR0YWNobWVudFVwbG9hZC5lbWl0KGZpbGUpO1xuICB9XG5cbiAgYXR0YWNobWVudERlbGV0ZWQodXBsb2FkOiBBdHRhY2htZW50VXBsb2FkKSB7XG4gICAgdGhpcy5kZWxldGVBdHRhY2htZW50LmVtaXQodXBsb2FkKTtcbiAgfVxuXG4gIHRyYWNrQnlGaWxlKF86IG51bWJlciwgaXRlbTogQXR0YWNobWVudFVwbG9hZCkge1xuICAgIHJldHVybiBpdGVtLmZpbGU7XG4gIH1cbn1cbiIsIkBpZiAoXG4gIChhdHRhY2htZW50VXBsb2FkcyQgfCBhc3luYyk/Lmxlbmd0aCB8fFxuICAoY3VzdG9tQXR0YWNobWVudHMubGVuZ3RoID4gMCAmJiBjdXN0b21BdHRhY2htZW50c1ByZXZpZXcpXG4pIHtcbiAgPGRpdiBjbGFzcz1cInN0ci1jaGF0X19hdHRhY2htZW50LXByZXZpZXctbGlzdFwiPlxuICAgIDxkaXYgY2xhc3M9XCJzdHItY2hhdF9fYXR0YWNobWVudC1saXN0LXNjcm9sbC1jb250YWluZXJcIj5cbiAgICAgIEBmb3IgKFxuICAgICAgICBhdHRhY2htZW50VXBsb2FkIG9mIGF0dGFjaG1lbnRVcGxvYWRzJCB8IGFzeW5jO1xuICAgICAgICB0cmFjayBhdHRhY2htZW50VXBsb2FkLmZpbGVcbiAgICAgICkge1xuICAgICAgICBAaWYgKGF0dGFjaG1lbnRVcGxvYWQudHlwZSA9PT0gXCJpbWFnZVwiKSB7XG4gICAgICAgICAgPGRpdlxuICAgICAgICAgICAgY2xhc3M9XCJzdHItY2hhdF9fYXR0YWNobWVudC1wcmV2aWV3LWltYWdlXCJcbiAgICAgICAgICAgIGRhdGEtdGVzdGNsYXNzPVwiYXR0YWNobWVudC1pbWFnZS1wcmV2aWV3XCJcbiAgICAgICAgICA+XG4gICAgICAgICAgICA8bmctY29udGFpbmVyXG4gICAgICAgICAgICAgICpuZ1RlbXBsYXRlT3V0bGV0PVwiXG4gICAgICAgICAgICAgICAgZGVsZXRlQnV0dG9uO1xuICAgICAgICAgICAgICAgIGNvbnRleHQ6IHsgYXR0YWNobWVudFVwbG9hZDogYXR0YWNobWVudFVwbG9hZCB9XG4gICAgICAgICAgICAgIFwiXG4gICAgICAgICAgICAvPlxuICAgICAgICAgICAgQGlmIChhdHRhY2htZW50VXBsb2FkLnN0YXRlID09PSBcInVwbG9hZGluZ1wiKSB7XG4gICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJzdHItY2hhdF9fYXR0YWNobWVudC1wcmV2aWV3LWltYWdlLWxvYWRpbmdcIj5cbiAgICAgICAgICAgICAgICA8c3RyZWFtLWxvYWRpbmctaW5kaWNhdG9yLXBsYWNlaG9sZGVyXG4gICAgICAgICAgICAgICAgICBkYXRhLXRlc3RjbGFzcz1cImxvYWRpbmctaW5kaWNhdG9yXCJcbiAgICAgICAgICAgICAgICAvPlxuICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIDxuZy1jb250YWluZXJcbiAgICAgICAgICAgICAgKm5nVGVtcGxhdGVPdXRsZXQ9XCJcbiAgICAgICAgICAgICAgICByZXRyeUJ1dHRvbjtcbiAgICAgICAgICAgICAgICBjb250ZXh0OiB7IGF0dGFjaG1lbnRVcGxvYWQ6IGF0dGFjaG1lbnRVcGxvYWQgfVxuICAgICAgICAgICAgICBcIlxuICAgICAgICAgICAgLz5cbiAgICAgICAgICAgIEBpZiAoYXR0YWNobWVudFVwbG9hZC51cmwgfHwgYXR0YWNobWVudFVwbG9hZC5wcmV2aWV3VXJpKSB7XG4gICAgICAgICAgICAgIDxpbWdcbiAgICAgICAgICAgICAgICBjbGFzcz1cInN0ci1jaGF0X19hdHRhY2htZW50LXByZXZpZXctdGh1bWJuYWlsXCJcbiAgICAgICAgICAgICAgICBkYXRhLXRlc3RjbGFzcz1cImF0dGFjaG1lbnQtaW1hZ2VcIlxuICAgICAgICAgICAgICAgIHNyYz1cInt7XG4gICAgICAgICAgICAgICAgICBhdHRhY2htZW50VXBsb2FkLnVybFxuICAgICAgICAgICAgICAgICAgICA/IGF0dGFjaG1lbnRVcGxvYWQudXJsXG4gICAgICAgICAgICAgICAgICAgIDogYXR0YWNobWVudFVwbG9hZC5wcmV2aWV3VXJpXG4gICAgICAgICAgICAgICAgfX1cIlxuICAgICAgICAgICAgICAgIGFsdD1cInt7IGF0dGFjaG1lbnRVcGxvYWQuZmlsZS5uYW1lIH19XCJcbiAgICAgICAgICAgICAgLz5cbiAgICAgICAgICAgIH1cbiAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgfVxuICAgICAgICBAaWYgKFxuICAgICAgICAgIGF0dGFjaG1lbnRVcGxvYWQudHlwZSA9PT0gXCJmaWxlXCIgfHxcbiAgICAgICAgICBhdHRhY2htZW50VXBsb2FkLnR5cGUgPT09IFwidmlkZW9cIiB8fFxuICAgICAgICAgIGF0dGFjaG1lbnRVcGxvYWQudHlwZSA9PT0gXCJ2b2ljZVJlY29yZGluZ1wiXG4gICAgICAgICkge1xuICAgICAgICAgIDxkaXZcbiAgICAgICAgICAgIGNsYXNzPVwic3RyLWNoYXRfX2F0dGFjaG1lbnQtcHJldmlldy1maWxlIHN0ci1jaGF0X19hdHRhY2htZW50LXByZXZpZXctdHlwZS17e1xuICAgICAgICAgICAgICBhdHRhY2htZW50VXBsb2FkLnR5cGVcbiAgICAgICAgICAgIH19XCJcbiAgICAgICAgICAgIGRhdGEtdGVzdGNsYXNzPVwiYXR0YWNobWVudC1maWxlLXByZXZpZXdcIlxuICAgICAgICAgID5cbiAgICAgICAgICAgIDxzdHJlYW0taWNvbi1wbGFjZWhvbGRlclxuICAgICAgICAgICAgICBjbGFzcz1cInN0ci1jaGF0X19hdHRhY2htZW50LXByZXZpZXctZmlsZS1pY29uXCJcbiAgICAgICAgICAgICAgaWNvbj1cInVuc3BlY2lmaWVkLWZpbGV0eXBlXCJcbiAgICAgICAgICAgIC8+XG4gICAgICAgICAgICA8ZGl2IGNsYXNzPVwic3RyLWNoYXRfX2F0dGFjaG1lbnQtcHJldmlldy1maWxlLWVuZFwiPlxuICAgICAgICAgICAgICA8ZGl2XG4gICAgICAgICAgICAgICAgY2xhc3M9XCJzdHItY2hhdF9fYXR0YWNobWVudC1wcmV2aWV3LWZpbGUtbmFtZVwiXG4gICAgICAgICAgICAgICAgdGl0bGU9XCJ7eyBhdHRhY2htZW50VXBsb2FkLmZpbGUubmFtZSB9fVwiXG4gICAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgICB7eyBhdHRhY2htZW50VXBsb2FkLmZpbGUubmFtZSB9fVxuICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgQGlmIChhdHRhY2htZW50VXBsb2FkLnN0YXRlID09PSBcInN1Y2Nlc3NcIikge1xuICAgICAgICAgICAgICAgIDxhXG4gICAgICAgICAgICAgICAgICBjbGFzcz1cInN0ci1jaGF0X19hdHRhY2htZW50LXByZXZpZXctZmlsZS1kb3dubG9hZFwiXG4gICAgICAgICAgICAgICAgICBkYXRhLXRlc3RjbGFzcz1cImZpbGUtZG93bmxvYWQtbGlua1wiXG4gICAgICAgICAgICAgICAgICBkb3dubG9hZFxuICAgICAgICAgICAgICAgICAgaHJlZj1cInt7IGF0dGFjaG1lbnRVcGxvYWQudXJsIH19XCJcbiAgICAgICAgICAgICAgICAgIChjbGljayk9XCJcbiAgICAgICAgICAgICAgICAgICAgYXR0YWNobWVudFVwbG9hZC51cmwgPyBudWxsIDogJGV2ZW50LnByZXZlbnREZWZhdWx0KClcbiAgICAgICAgICAgICAgICAgIFwiXG4gICAgICAgICAgICAgICAgICAoa2V5dXAuZW50ZXIpPVwiXG4gICAgICAgICAgICAgICAgICAgIGF0dGFjaG1lbnRVcGxvYWQudXJsID8gbnVsbCA6ICRldmVudC5wcmV2ZW50RGVmYXVsdCgpXG4gICAgICAgICAgICAgICAgICBcIlxuICAgICAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgICAgIDxzdHJlYW0taWNvbi1wbGFjZWhvbGRlciBpY29uPVwiZG93bmxvYWRcIiAvPlxuICAgICAgICAgICAgICAgIDwvYT5cbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICBAaWYgKGF0dGFjaG1lbnRVcGxvYWQuc3RhdGUgPT09IFwidXBsb2FkaW5nXCIpIHtcbiAgICAgICAgICAgICAgICA8c3RyZWFtLWxvYWRpbmctaW5kaWNhdG9yLXBsYWNlaG9sZGVyXG4gICAgICAgICAgICAgICAgICBkYXRhLXRlc3RjbGFzcz1cImxvYWRpbmctaW5kaWNhdG9yXCJcbiAgICAgICAgICAgICAgICAvPlxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgIDxuZy1jb250YWluZXJcbiAgICAgICAgICAgICAgKm5nVGVtcGxhdGVPdXRsZXQ9XCJcbiAgICAgICAgICAgICAgICBkZWxldGVCdXR0b247XG4gICAgICAgICAgICAgICAgY29udGV4dDogeyBhdHRhY2htZW50VXBsb2FkOiBhdHRhY2htZW50VXBsb2FkIH1cbiAgICAgICAgICAgICAgXCJcbiAgICAgICAgICAgIC8+XG4gICAgICAgICAgICA8bmctY29udGFpbmVyXG4gICAgICAgICAgICAgICpuZ1RlbXBsYXRlT3V0bGV0PVwiXG4gICAgICAgICAgICAgICAgcmV0cnlCdXR0b247XG4gICAgICAgICAgICAgICAgY29udGV4dDogeyBhdHRhY2htZW50VXBsb2FkOiBhdHRhY2htZW50VXBsb2FkIH1cbiAgICAgICAgICAgICAgXCJcbiAgICAgICAgICAgIC8+XG4gICAgICAgICAgPC9kaXY+XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIEBpZiAoY3VzdG9tQXR0YWNobWVudHNQcmV2aWV3KSB7XG4gICAgICAgIDxuZy10ZW1wbGF0ZVxuICAgICAgICAgICpuZ1RlbXBsYXRlT3V0bGV0PVwiXG4gICAgICAgICAgICBjdXN0b21BdHRhY2htZW50c1ByZXZpZXc7XG4gICAgICAgICAgICBjb250ZXh0OiB7IHNlcnZpY2U6IGF0dGFjaG1lbnRTZXJ2aWNlIH1cbiAgICAgICAgICBcIlxuICAgICAgICAvPlxuICAgICAgfVxuICAgIDwvZGl2PlxuICA8L2Rpdj5cbn1cblxuPG5nLXRlbXBsYXRlICNkZWxldGVCdXR0b24gbGV0LWF0dGFjaG1lbnRVcGxvYWQ9XCJhdHRhY2htZW50VXBsb2FkXCI+XG4gIDxkaXZcbiAgICBjbGFzcz1cInN0ci1jaGF0X19hdHRhY2htZW50LXByZXZpZXctZGVsZXRlXCJcbiAgICBkYXRhLXRlc3RjbGFzcz1cImZpbGUtZGVsZXRlXCJcbiAgICByb2xlPVwiYnV0dG9uXCJcbiAgICAoY2xpY2spPVwiYXR0YWNobWVudERlbGV0ZWQoYXR0YWNobWVudFVwbG9hZClcIlxuICAgIChrZXl1cC5lbnRlcik9XCJhdHRhY2htZW50RGVsZXRlZChhdHRhY2htZW50VXBsb2FkKVwiXG4gID5cbiAgICA8c3RyZWFtLWljb24tcGxhY2Vob2xkZXIgaWNvbj1cImNsb3NlXCIgLz5cbiAgPC9kaXY+XG48L25nLXRlbXBsYXRlPlxuXG48bmctdGVtcGxhdGUgI3JldHJ5QnV0dG9uIGxldC1hdHRhY2htZW50VXBsb2FkPVwiYXR0YWNobWVudFVwbG9hZFwiPlxuICBAaWYgKGF0dGFjaG1lbnRVcGxvYWQuc3RhdGUgPT09IFwiZXJyb3JcIikge1xuICAgIDxkaXZcbiAgICAgIGRhdGEtdGVzdGNsYXNzPVwidXBsb2FkLXJldHJ5XCJcbiAgICAgIGNsYXNzPVwic3RyLWNoYXRfX2F0dGFjaG1lbnQtcHJldmlldy1lcnJvciBzdHItY2hhdF9fYXR0YWNobWVudC1wcmV2aWV3LWVycm9yLXt7XG4gICAgICAgIGF0dGFjaG1lbnRVcGxvYWQudHlwZSA9PT0gJ2ltYWdlJyA/ICdpbWFnZScgOiAnZmlsZSdcbiAgICAgIH19XCJcbiAgICAgIChjbGljayk9XCJhdHRhY2htZW50VXBsb2FkUmV0cmllZChhdHRhY2htZW50VXBsb2FkLmZpbGUpXCJcbiAgICAgIChrZXl1cC5lbnRlcik9XCJhdHRhY2htZW50VXBsb2FkUmV0cmllZChhdHRhY2htZW50VXBsb2FkLmZpbGUpXCJcbiAgICA+XG4gICAgICA8c3RyZWFtLWljb24tcGxhY2Vob2xkZXIgaWNvbj1cInJldHJ5XCIgLz5cbiAgICA8L2Rpdj5cbiAgfVxuPC9uZy10ZW1wbGF0ZT5cbiJdfQ==