stream-chat-angular 1.3.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (64) hide show
  1. package/assets/i18n/en.d.ts +1 -0
  2. package/assets/version.d.ts +1 -1
  3. package/bundles/stream-chat-angular.umd.js +1196 -365
  4. package/bundles/stream-chat-angular.umd.js.map +1 -1
  5. package/esm2015/assets/i18n/en.js +2 -1
  6. package/esm2015/assets/version.js +2 -2
  7. package/esm2015/lib/attachment-list/attachment-list.component.js +3 -4
  8. package/esm2015/lib/attachment-preview-list/attachment-preview-list.component.js +38 -0
  9. package/esm2015/lib/attachment.service.js +190 -0
  10. package/esm2015/lib/channel.service.js +53 -4
  11. package/esm2015/lib/chat-client.service.js +16 -1
  12. package/esm2015/lib/injection-tokens.js +3 -0
  13. package/esm2015/lib/is-image-attachment.js +6 -0
  14. package/esm2015/lib/message/highlight-mentions.pipe.js +23 -0
  15. package/esm2015/lib/message/message.component.js +3 -2
  16. package/esm2015/lib/message-actions-box/message-actions-box.component.js +43 -12
  17. package/esm2015/lib/message-input/autocomplete-textarea/autocomplete-textarea.component.js +145 -0
  18. package/esm2015/lib/message-input/message-input-config.service.js +19 -0
  19. package/esm2015/lib/message-input/message-input.component.js +122 -140
  20. package/esm2015/lib/message-input/textarea/textarea.component.js +42 -0
  21. package/esm2015/lib/message-input/textarea.directive.js +69 -0
  22. package/esm2015/lib/message-input/textarea.interface.js +2 -0
  23. package/esm2015/lib/message-list/message-list.component.js +19 -3
  24. package/esm2015/lib/message-preview.js +3 -2
  25. package/esm2015/lib/modal/modal.component.js +63 -0
  26. package/esm2015/lib/notification-list/notification-list.component.js +1 -1
  27. package/esm2015/lib/notification.service.js +1 -1
  28. package/esm2015/lib/stream-autocomplete-textarea.module.js +33 -0
  29. package/esm2015/lib/stream-avatar.module.js +19 -0
  30. package/esm2015/lib/stream-chat.module.js +25 -11
  31. package/esm2015/lib/stream-textarea.module.js +31 -0
  32. package/esm2015/lib/types.js +1 -1
  33. package/esm2015/public-api.js +19 -1
  34. package/fesm2015/stream-chat-angular.js +955 -241
  35. package/fesm2015/stream-chat-angular.js.map +1 -1
  36. package/lib/attachment-preview-list/attachment-preview-list.component.d.ts +14 -0
  37. package/lib/attachment.service.d.ts +25 -0
  38. package/lib/channel.service.d.ts +6 -2
  39. package/lib/chat-client.service.d.ts +1 -0
  40. package/lib/injection-tokens.d.ts +3 -0
  41. package/lib/is-image-attachment.d.ts +2 -0
  42. package/lib/message/highlight-mentions.pipe.d.ts +8 -0
  43. package/lib/message/message.component.d.ts +1 -0
  44. package/lib/message-actions-box/message-actions-box.component.d.ts +11 -4
  45. package/lib/message-input/autocomplete-textarea/autocomplete-textarea.component.d.ts +42 -0
  46. package/lib/message-input/message-input-config.service.d.ts +14 -0
  47. package/lib/message-input/message-input.component.d.ts +30 -20
  48. package/lib/message-input/textarea/textarea.component.d.ts +16 -0
  49. package/lib/message-input/textarea.directive.d.ts +21 -0
  50. package/lib/message-input/textarea.interface.d.ts +12 -0
  51. package/lib/message-list/message-list.component.d.ts +1 -1
  52. package/lib/message-preview.d.ts +1 -1
  53. package/lib/modal/modal.component.d.ts +16 -0
  54. package/lib/notification-list/notification-list.component.d.ts +3 -3
  55. package/lib/notification.service.d.ts +2 -2
  56. package/lib/stream-autocomplete-textarea.module.d.ts +11 -0
  57. package/lib/stream-avatar.module.d.ts +9 -0
  58. package/lib/stream-chat.module.d.ts +23 -19
  59. package/lib/stream-textarea.module.d.ts +9 -0
  60. package/lib/types.d.ts +7 -1
  61. package/package.json +3 -2
  62. package/public-api.d.ts +18 -0
  63. package/src/assets/i18n/en.ts +1 -0
  64. package/src/assets/version.ts +1 -1
@@ -1,11 +1,11 @@
1
1
  import { __awaiter } from 'tslib';
2
2
  import * as i0 from '@angular/core';
3
- import { Injectable, Component, Input, EventEmitter, Output, ViewChild, HostBinding, NgModule } from '@angular/core';
3
+ import { Injectable, Component, Input, InjectionToken, EventEmitter, Directive, Output, Inject, ViewChild, Pipe, HostBinding, NgModule } from '@angular/core';
4
4
  import { BehaviorSubject, ReplaySubject, of, Subject } from 'rxjs';
5
5
  import { StreamChat } from 'stream-chat';
6
- import { map, first, catchError, startWith, distinctUntilChanged, filter, tap } from 'rxjs/operators';
6
+ import { map, first, catchError, startWith, distinctUntilChanged, filter, debounceTime, tap } from 'rxjs/operators';
7
7
  import { v4 } from 'uuid';
8
- import * as i4 from '@ngx-translate/core';
8
+ import * as i1 from '@ngx-translate/core';
9
9
  import { TranslateModule } from '@ngx-translate/core';
10
10
  import * as i5 from '@angular/common';
11
11
  import { CommonModule } from '@angular/common';
@@ -14,8 +14,10 @@ import calendar from 'dayjs/plugin/calendar';
14
14
  import * as i2 from '@ctrl/ngx-emoji-mart/ngx-emoji';
15
15
  import { EmojiModule } from '@ctrl/ngx-emoji-mart/ngx-emoji';
16
16
  import prettybytes from 'pretty-bytes';
17
+ import * as i4 from 'angular-mentions';
18
+ import { MentionModule } from 'angular-mentions';
17
19
 
18
- const version = '1.3.0';
20
+ const version = '2.0.0';
19
21
 
20
22
  class NotificationService {
21
23
  constructor() {
@@ -118,6 +120,21 @@ class ChatClientService {
118
120
  yield this.chatClient.flagMessage(messageId);
119
121
  });
120
122
  }
123
+ autocompleteUsers(searchTerm) {
124
+ return __awaiter(this, void 0, void 0, function* () {
125
+ if (!searchTerm) {
126
+ return [];
127
+ }
128
+ const result = yield this.chatClient.queryUsers({
129
+ $or: [
130
+ { id: { $autocomplete: searchTerm } },
131
+ { name: { $autocomplete: searchTerm } },
132
+ ],
133
+ id: { $ne: this.chatClient.userID },
134
+ });
135
+ return result.users;
136
+ });
137
+ }
121
138
  }
122
139
  ChatClientService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: ChatClientService, deps: [{ token: i0.NgZone }, { token: i0.ApplicationRef }, { token: NotificationService }], target: i0.ɵɵFactoryTarget.Injectable });
123
140
  ChatClientService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: ChatClientService, providedIn: 'root' });
@@ -128,7 +145,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImpor
128
145
  }]
129
146
  }], ctorParameters: function () { return [{ type: i0.NgZone }, { type: i0.ApplicationRef }, { type: NotificationService }]; } });
130
147
 
131
- const createMessagePreview = (user, text, attachments) => {
148
+ const createMessagePreview = (user, text, attachments, mentionedUsers) => {
132
149
  const clientSideId = `${user.id}-${v4()}`;
133
150
  return {
134
151
  __html: text,
@@ -141,6 +158,7 @@ const createMessagePreview = (user, text, attachments) => {
141
158
  type: 'regular',
142
159
  user,
143
160
  attachments,
161
+ mentioned_users: mentionedUsers,
144
162
  };
145
163
  };
146
164
 
@@ -178,7 +196,8 @@ class ChannelService {
178
196
  this.activeChannelMessages$ = this.activeChannelMessagesSubject.pipe(map((messages) => {
179
197
  const channel = this.activeChannelSubject.getValue();
180
198
  return messages.map((message) => {
181
- if (this.isStreamMessage(message)) {
199
+ if (this.isStreamMessage(message) &&
200
+ this.isFormatMessageResponse(message)) {
182
201
  return message;
183
202
  }
184
203
  else if (this.isFormatMessageResponse(message)) {
@@ -258,9 +277,9 @@ class ChannelService {
258
277
  .getValue()) === null || _a === void 0 ? void 0 : _a.deleteReaction(messageId, reactionType));
259
278
  });
260
279
  }
261
- sendMessage(text, attachments = []) {
280
+ sendMessage(text, attachments = [], mentionedUsers = []) {
262
281
  return __awaiter(this, void 0, void 0, function* () {
263
- const preview = createMessagePreview(this.chatClientService.chatClient.user, text, attachments);
282
+ const preview = createMessagePreview(this.chatClientService.chatClient.user, text, attachments, mentionedUsers);
264
283
  const channel = this.activeChannelSubject.getValue();
265
284
  preview.readBy = [];
266
285
  channel.state.addMessageSorted(preview, true);
@@ -274,6 +293,16 @@ class ChannelService {
274
293
  yield this.sendMessageRequest(message);
275
294
  });
276
295
  }
296
+ updateMessage(message) {
297
+ return __awaiter(this, void 0, void 0, function* () {
298
+ yield this.chatClientService.chatClient.updateMessage(message);
299
+ });
300
+ }
301
+ deleteMessage(message) {
302
+ return __awaiter(this, void 0, void 0, function* () {
303
+ yield this.chatClientService.chatClient.deleteMessage(message.id);
304
+ });
305
+ }
277
306
  uploadAttachments(uploads) {
278
307
  return __awaiter(this, void 0, void 0, function* () {
279
308
  const result = [];
@@ -307,7 +336,32 @@ class ChannelService {
307
336
  : channel.deleteFile(attachmentUpload.url));
308
337
  });
309
338
  }
339
+ autocompleteMembers(searchTerm) {
340
+ return __awaiter(this, void 0, void 0, function* () {
341
+ const activeChannel = this.activeChannelSubject.getValue();
342
+ if (!activeChannel) {
343
+ return [];
344
+ }
345
+ if (Object.keys(activeChannel.state.members).length <= 100) {
346
+ return Object.values(activeChannel.state.members).filter((m) => { var _a; return ((_a = m.user) === null || _a === void 0 ? void 0 : _a.id) !== this.chatClientService.chatClient.userID; });
347
+ }
348
+ else {
349
+ if (!searchTerm) {
350
+ return [];
351
+ }
352
+ const result = yield activeChannel.queryMembers({
353
+ $or: [
354
+ { id: { $autocomplete: searchTerm } },
355
+ { name: { $autocomplete: searchTerm } },
356
+ ],
357
+ id: { $ne: this.chatClientService.chatClient.userID },
358
+ });
359
+ return Object.values(result.members);
360
+ }
361
+ });
362
+ }
310
363
  sendMessageRequest(preview) {
364
+ var _a;
311
365
  return __awaiter(this, void 0, void 0, function* () {
312
366
  const channel = this.activeChannelSubject.getValue();
313
367
  this.activeChannelMessagesSubject.next([...channel.state.messages]);
@@ -315,6 +369,7 @@ class ChannelService {
315
369
  yield channel.sendMessage({
316
370
  text: preview.text,
317
371
  attachments: preview.attachments,
372
+ mentioned_users: (_a = preview.mentioned_users) === null || _a === void 0 ? void 0 : _a.map((u) => u.id),
318
373
  id: preview.id,
319
374
  });
320
375
  }
@@ -408,6 +463,8 @@ class ChannelService {
408
463
  .subscribe((c) => void (c === null || c === void 0 ? void 0 : c.markRead()));
409
464
  });
410
465
  }));
466
+ this.activeChannelSubscriptions.push(channel.on('message.updated', (event) => this.messageUpdated(event)));
467
+ this.activeChannelSubscriptions.push(channel.on('message.deleted', (event) => this.messageUpdated(event)));
411
468
  this.activeChannelSubscriptions.push(channel.on('reaction.new', (e) => this.messageReactionEventReceived(e)));
412
469
  this.activeChannelSubscriptions.push(channel.on('reaction.deleted', (e) => this.messageReactionEventReceived(e)));
413
470
  this.activeChannelSubscriptions.push(channel.on('reaction.updated', (e) => this.messageReactionEventReceived(e)));
@@ -423,6 +480,16 @@ class ChannelService {
423
480
  this.activeChannelMessagesSubject.next(this.activeChannelMessagesSubject.getValue());
424
481
  }));
425
482
  }
483
+ messageUpdated(event) {
484
+ this.ngZone.run(() => {
485
+ const messages = this.activeChannelMessagesSubject.getValue();
486
+ const messageIndex = messages.findIndex((m) => { var _a; return m.id === ((_a = event.message) === null || _a === void 0 ? void 0 : _a.id); });
487
+ if (messageIndex !== -1 && event.message) {
488
+ messages[messageIndex] = event.message;
489
+ this.activeChannelMessagesSubject.next([...messages]);
490
+ }
491
+ });
492
+ }
426
493
  messageReactionEventReceived(e) {
427
494
  this.ngZone.run(() => {
428
495
  var _a, _b, _c, _d;
@@ -680,6 +747,195 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImpor
680
747
  }]
681
748
  }], ctorParameters: function () { return []; } });
682
749
 
750
+ const isImageAttachment = (attachment) => {
751
+ return (attachment.type === 'image' &&
752
+ !attachment.title_link &&
753
+ !attachment.og_scrape_url);
754
+ };
755
+
756
+ class AttachmentService {
757
+ constructor(channelService, notificationService) {
758
+ this.channelService = channelService;
759
+ this.notificationService = notificationService;
760
+ this.attachmentUploadInProgressCounterSubject = new BehaviorSubject(0);
761
+ this.attachmentUploadsSubject = new BehaviorSubject([]);
762
+ this.attachmentUploadInProgressCounter$ =
763
+ this.attachmentUploadInProgressCounterSubject.asObservable();
764
+ this.attachmentUploads$ = this.attachmentUploadsSubject.asObservable();
765
+ }
766
+ resetAttachmentUploads() {
767
+ this.attachmentUploadsSubject.next([]);
768
+ }
769
+ filesSelected(fileList) {
770
+ return __awaiter(this, void 0, void 0, function* () {
771
+ if (!fileList) {
772
+ return;
773
+ }
774
+ const imageFiles = [];
775
+ const dataFiles = [];
776
+ Array.from(fileList).forEach((file) => {
777
+ if (file.type.startsWith('image/') && !file.type.endsWith('.photoshop')) {
778
+ // photoshop files begin with 'image/'
779
+ imageFiles.push(file);
780
+ }
781
+ else {
782
+ dataFiles.push(file);
783
+ }
784
+ });
785
+ imageFiles.forEach((f) => this.createPreview(f));
786
+ const newUploads = [
787
+ ...imageFiles.map((file) => ({
788
+ file,
789
+ state: 'uploading',
790
+ type: 'image',
791
+ })),
792
+ ...dataFiles.map((file) => ({
793
+ file,
794
+ state: 'uploading',
795
+ type: 'file',
796
+ })),
797
+ ];
798
+ this.attachmentUploadsSubject.next([
799
+ ...this.attachmentUploadsSubject.getValue(),
800
+ ...newUploads,
801
+ ]);
802
+ yield this.uploadAttachments(newUploads);
803
+ });
804
+ }
805
+ retryAttachmentUpload(file) {
806
+ return __awaiter(this, void 0, void 0, function* () {
807
+ const attachmentUploads = this.attachmentUploadsSubject.getValue();
808
+ const upload = attachmentUploads.find((u) => u.file === file);
809
+ if (!upload) {
810
+ return;
811
+ }
812
+ upload.state = 'uploading';
813
+ this.attachmentUploadsSubject.next([...attachmentUploads]);
814
+ yield this.uploadAttachments([upload]);
815
+ });
816
+ }
817
+ deleteAttachment(upload) {
818
+ return __awaiter(this, void 0, void 0, function* () {
819
+ const attachmentUploads = this.attachmentUploadsSubject.getValue();
820
+ if (upload.state === 'success') {
821
+ try {
822
+ yield this.channelService.deleteAttachment(upload);
823
+ attachmentUploads.splice(attachmentUploads.indexOf(upload), 1);
824
+ }
825
+ catch (error) {
826
+ this.notificationService.addTemporaryNotification('streamChat.Error deleting attachment');
827
+ }
828
+ }
829
+ else {
830
+ attachmentUploads.splice(attachmentUploads.indexOf(upload), 1);
831
+ }
832
+ this.attachmentUploadsSubject.next([...attachmentUploads]);
833
+ });
834
+ }
835
+ mapToAttachments() {
836
+ const attachmentUploads = this.attachmentUploadsSubject.getValue();
837
+ return attachmentUploads
838
+ .filter((r) => r.state === 'success')
839
+ .map((r) => {
840
+ var _a, _b, _c;
841
+ const attachment = {
842
+ type: r.type,
843
+ };
844
+ if (r.type === 'image') {
845
+ attachment.fallback = (_a = r.file) === null || _a === void 0 ? void 0 : _a.name;
846
+ attachment.image_url = r.url;
847
+ }
848
+ else {
849
+ attachment.asset_url = r.url;
850
+ attachment.title = (_b = r.file) === null || _b === void 0 ? void 0 : _b.name;
851
+ attachment.file_size = (_c = r.file) === null || _c === void 0 ? void 0 : _c.size;
852
+ }
853
+ return attachment;
854
+ });
855
+ }
856
+ createFromAttachments(attachments) {
857
+ const attachmentUploads = [];
858
+ attachments.forEach((attachment) => {
859
+ if (isImageAttachment(attachment)) {
860
+ attachmentUploads.push({
861
+ url: (attachment.img_url ||
862
+ attachment.thumb_url ||
863
+ attachment.image_url),
864
+ state: 'success',
865
+ type: 'image',
866
+ file: {
867
+ name: attachment.fallback,
868
+ },
869
+ });
870
+ }
871
+ else if (attachment.type === 'file') {
872
+ attachmentUploads.push({
873
+ url: attachment.asset_url,
874
+ state: 'success',
875
+ file: {
876
+ name: attachment.title,
877
+ size: attachment.file_size,
878
+ },
879
+ type: 'file',
880
+ });
881
+ }
882
+ });
883
+ if (attachmentUploads.length > 0) {
884
+ this.attachmentUploadsSubject.next([
885
+ ...this.attachmentUploadsSubject.getValue(),
886
+ ...attachmentUploads,
887
+ ]);
888
+ }
889
+ }
890
+ createPreview(file) {
891
+ const reader = new FileReader();
892
+ reader.onload = (event) => {
893
+ var _a;
894
+ const attachmentUploads = this.attachmentUploadsSubject.getValue();
895
+ const upload = attachmentUploads.find((upload) => upload.file === file);
896
+ if (!upload) {
897
+ return;
898
+ }
899
+ upload.previewUri = ((_a = event.target) === null || _a === void 0 ? void 0 : _a.result) || undefined;
900
+ this.attachmentUploadsSubject.next([...attachmentUploads]);
901
+ };
902
+ reader.readAsDataURL(file);
903
+ }
904
+ uploadAttachments(uploads) {
905
+ return __awaiter(this, void 0, void 0, function* () {
906
+ const attachmentUploads = this.attachmentUploadsSubject.getValue();
907
+ this.attachmentUploadInProgressCounterSubject.next(this.attachmentUploadInProgressCounterSubject.getValue() + 1);
908
+ const result = yield this.channelService.uploadAttachments(uploads);
909
+ result.forEach((r) => {
910
+ const upload = attachmentUploads.find((upload) => upload.file === r.file);
911
+ if (!upload) {
912
+ if (r.url) {
913
+ void this.channelService.deleteAttachment(r);
914
+ }
915
+ return;
916
+ }
917
+ upload.state = r.state;
918
+ upload.url = r.url;
919
+ if (upload.state === 'error') {
920
+ this.notificationService.addTemporaryNotification(upload.type === 'image'
921
+ ? 'streamChat.Error uploading image'
922
+ : 'streamChat.Error uploading file');
923
+ }
924
+ });
925
+ this.attachmentUploadInProgressCounterSubject.next(this.attachmentUploadInProgressCounterSubject.getValue() - 1);
926
+ this.attachmentUploadsSubject.next([...attachmentUploads]);
927
+ });
928
+ }
929
+ }
930
+ AttachmentService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: AttachmentService, deps: [{ token: ChannelService }, { token: NotificationService }], target: i0.ɵɵFactoryTarget.Injectable });
931
+ AttachmentService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: AttachmentService, providedIn: 'root' });
932
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: AttachmentService, decorators: [{
933
+ type: Injectable,
934
+ args: [{
935
+ providedIn: 'root',
936
+ }]
937
+ }], ctorParameters: function () { return [{ type: ChannelService }, { type: NotificationService }]; } });
938
+
683
939
  const en = {
684
940
  streamChat: {
685
941
  '1 reply': '1 reply',
@@ -705,6 +961,7 @@ const en = {
705
961
  'Error unmuting a user ...': 'Error unmuting a user ...',
706
962
  'Error uploading file': 'Error uploading file',
707
963
  'Error uploading image': 'Error uploading image',
964
+ 'Error deleting attachment': 'Error deleting attachment',
708
965
  'Error · Unsent': 'Error · Unsent',
709
966
  'Error: {{ errorMessage }}': 'Error: {{ errorMessage }}',
710
967
  Flag: 'Flag',
@@ -772,14 +1029,14 @@ class StreamI18nService {
772
1029
  this.translteService.setTranslation(lang, { streamChat: Object.assign(Object.assign({}, en.streamChat), overrides) }, true);
773
1030
  }
774
1031
  }
775
- StreamI18nService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: StreamI18nService, deps: [{ token: i4.TranslateService }], target: i0.ɵɵFactoryTarget.Injectable });
1032
+ StreamI18nService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: StreamI18nService, deps: [{ token: i1.TranslateService }], target: i0.ɵɵFactoryTarget.Injectable });
776
1033
  StreamI18nService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: StreamI18nService, providedIn: 'root' });
777
1034
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: StreamI18nService, decorators: [{
778
1035
  type: Injectable,
779
1036
  args: [{
780
1037
  providedIn: 'root',
781
1038
  }]
782
- }], ctorParameters: function () { return [{ type: i4.TranslateService }]; } });
1039
+ }], ctorParameters: function () { return [{ type: i1.TranslateService }]; } });
783
1040
 
784
1041
  class AvatarComponent {
785
1042
  constructor() {
@@ -813,7 +1070,7 @@ class IconComponent {
813
1070
  constructor() { }
814
1071
  }
815
1072
  IconComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: IconComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
816
- IconComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.5", type: IconComponent, selector: "stream-icon", inputs: { icon: "icon", size: "size" }, ngImport: i0, template: "<svg\n data-testid=\"action-icon\"\n *ngIf=\"icon === 'action-icon'\"\n height=\"4\"\n viewBox=\"0 0 11 4\"\n width=\"11\"\n xmlns=\"http://www.w3.org/2000/svg\"\n>\n <path\n d=\"M1.5 3a1.5 1.5 0 1 1 0-3 1.5 1.5 0 0 1 0 3zm4 0a1.5 1.5 0 1 1 0-3 1.5 1.5 0 0 1 0 3zm4 0a1.5 1.5 0 1 1 0-3 1.5 1.5 0 0 1 0 3z\"\n fillRule=\"nonzero\"\n />\n</svg>\n<svg\n *ngIf=\"icon === 'delivered-icon'\"\n height=\"16\"\n width=\"16\"\n xmlns=\"http://www.w3.org/2000/svg\"\n data-testid=\"delivered-icon\"\n>\n <path\n d=\"M8 0a8 8 0 1 1 0 16A8 8 0 0 1 8 0zm3.72 6.633a.955.955 0 1 0-1.352-1.352L6.986 8.663 5.633 7.31A.956.956 0 1 0 4.28 8.663l2.029 2.028a.956.956 0 0 0 1.353 0l4.058-4.058z\"\n fill=\"#006CFF\"\n fillRule=\"evenodd\"\n />\n</svg>\n<svg\n *ngIf=\"icon === 'reaction-icon'\"\n height=\"12\"\n viewBox=\"0 0 12 12\"\n width=\"12\"\n xmlns=\"http://www.w3.org/2000/svg\"\n data-testid=\"reaction-icon\"\n>\n <g clipRule=\"evenodd\" fillRule=\"evenodd\">\n <path\n d=\"M6 1.2C3.3 1.2 1.2 3.3 1.2 6c0 2.7 2.1 4.8 4.8 4.8 2.7 0 4.8-2.1 4.8-4.8 0-2.7-2.1-4.8-4.8-4.8zM0 6c0-3.3 2.7-6 6-6s6 2.7 6 6-2.7 6-6 6-6-2.7-6-6z\"\n ></path>\n <path\n d=\"M5.4 4.5c0 .5-.4.9-.9.9s-.9-.4-.9-.9.4-.9.9-.9.9.4.9.9zM8.4 4.5c0 .5-.4.9-.9.9s-.9-.4-.9-.9.4-.9.9-.9.9.4.9.9zM3.3 6.7c.3-.2.6-.1.8.1.3.4.8.9 1.5 1 .6.2 1.4.1 2.4-1 .2-.2.6-.3.8 0 .2.2.3.6 0 .8-1.1 1.3-2.4 1.7-3.5 1.5-1-.2-1.8-.9-2.2-1.5-.2-.3-.1-.7.2-.9z\"\n ></path>\n </g>\n</svg>\n<svg\n data-testid=\"connection-error\"\n *ngIf=\"icon === 'connection-error'\"\n width=\"78px\"\n height=\"78px\"\n viewBox=\"0 0 78 78\"\n version=\"1.1\"\n xmlns=\"http://www.w3.org/2000/svg\"\n xmlns:xlink=\"http://www.w3.org/1999/xlink\"\n>\n <!-- Generator: Sketch 52.6 (67491) - http://www.bohemiancoding.com/sketch -->\n <title>Combined Shape</title>\n <desc>Created with Sketch.</desc>\n <g\n id=\"Interactions\"\n stroke=\"none\"\n stroke-width=\"1\"\n fill=\"none\"\n fill-rule=\"evenodd\"\n >\n <g\n id=\"Connection-Error-_-Connectivity\"\n transform=\"translate(-270.000000, -30.000000)\"\n fill=\"#CF1F25\"\n >\n <g\n id=\"109-network-connection\"\n transform=\"translate(270.000000, 30.000000)\"\n >\n <path\n d=\"M66.4609744,11.414231 C81.6225232,26.5757798 81.6225232,51.157545 66.4609744,66.3188467 C51.2994256,81.4803954 26.7176604,81.4803954 11.5563587,66.3188467 C-3.60519004,51.1572979 -3.60519004,26.5755327 11.5563587,11.414231 C26.7179075,-3.74731776 51.2996727,-3.74731776 66.4609744,11.414231 Z M54.7853215,45.8823776 L54.7853215,40.5882574 C54.7853215,39.613638 53.9952341,38.8235506 53.0206147,38.8235506 L44.9576695,38.8235506 L41.428256,42.3529641 L51.255555,42.3529641 L51.255555,45.8823776 L54.7853215,45.8823776 Z M40.6659027,43.1153174 L37.8988425,45.8823776 L40.6659027,45.8823776 L40.6659027,43.1153174 Z M51.1764962,56.4702653 L58.2353232,56.4702653 C59.2099355,56.4702653 60.00003,55.6801708 60.00003,54.7055585 L60.00003,51.176145 C60.00003,50.2015327 59.2099355,49.4114382 58.2353232,49.4114382 L51.1764962,49.4114382 C50.2018839,49.4114382 49.4117894,50.2015327 49.4117894,51.176145 L49.4117894,54.7055585 C49.4117894,55.6801708 50.2018839,56.4702653 51.1764962,56.4702653 Z M35.2941353,56.4702653 L42.3529624,56.4702653 C43.3275746,56.4702653 44.1176691,55.6801708 44.1176691,54.7055585 L44.1176691,51.176145 C44.1176691,50.2015327 43.3275746,49.4114382 42.3529624,49.4114382 L35.2941353,49.4114382 C34.319523,49.4114382 33.5294285,50.2015327 33.5294285,51.176145 L33.5294285,54.7055585 C33.5294285,55.6801708 34.319523,56.4702653 35.2941353,56.4702653 Z M56.6964989,19.0874231 C56.007381,18.3985134 54.8903216,18.3985134 54.2012036,19.087423 L45.882376,27.4062507 L45.882376,19.4117761 C45.882376,18.4371568 45.0922885,17.6470693 44.1176692,17.6470693 L33.5294286,17.6470693 C32.5548092,17.6470694 31.7647218,18.4371568 31.7647218,19.4117761 L31.7647218,30.0000167 C31.7647219,30.9746363 32.5548092,31.7647237 33.5294285,31.7647237 L41.5239031,31.7647237 L34.4650761,38.8235508 L24.7058947,38.8235508 C23.7312753,38.8235508 22.9411879,39.6136382 22.9411879,40.5882575 L22.9411879,45.8823778 L26.4706014,45.8823778 L26.4706014,42.3529643 L30.9356624,42.3529643 L23.8768354,49.4117914 L19.4117743,49.4117914 C18.4371549,49.4117914 17.6470675,50.2018788 17.6470675,51.1764981 L17.6470675,54.7059117 C17.6504049,54.9674302 17.7129076,55.2248042 17.8298886,55.4587302 L16.4456526,56.8429662 C15.7446193,57.5200453 15.7252005,58.6372282 16.4022825,59.3382615 C17.0793616,60.0392948 18.1965445,60.0587136 18.8975778,59.3816316 C18.9122847,59.3674273 18.9267436,59.3529684 18.940948,59.3382615 L56.6964963,21.5830662 C57.3856425,20.8939094 57.3856425,19.7765747 56.6964963,19.0874179 Z\"\n id=\"Combined-Shape\"\n ></path>\n </g>\n </g>\n </g>\n</svg>\n<svg\n *ngIf=\"icon === 'send'\"\n data-testid=\"send\"\n height=\"17\"\n viewBox=\"0 0 18 17\"\n width=\"18\"\n xmlns=\"http://www.w3.org/2000/svg\"\n>\n <title translate>streamChat.Send</title>\n <path\n d=\"M0 17.015l17.333-8.508L0 0v6.617l12.417 1.89L0 10.397z\"\n fill=\"#006cff\"\n fillRule=\"evenodd\"\n />\n</svg>\n<svg\n *ngIf=\"icon === 'file-upload'\"\n data-testid=\"file-upload\"\n height=\"14\"\n width=\"14\"\n xmlns=\"http://www.w3.org/2000/svg\"\n>\n <title translate>streamChat.Attach files</title>\n <path\n d=\"M1.667.333h10.666c.737 0 1.334.597 1.334 1.334v10.666c0 .737-.597 1.334-1.334 1.334H1.667a1.333 1.333 0 0 1-1.334-1.334V1.667C.333.93.93.333 1.667.333zm2 1.334a1.667 1.667 0 1 0 0 3.333 1.667 1.667 0 0 0 0-3.333zm-2 9.333v1.333h10.666v-4l-2-2-4 4-2-2L1.667 11z\"\n fillRule=\"nonzero\"\n />\n</svg>\n<svg\n data-testid=\"retry\"\n *ngIf=\"icon === 'retry'\"\n width=\"22\"\n height=\"20\"\n viewBox=\"0 0 22 20\"\n xmlns=\"http://www.w3.org/2000/svg\"\n>\n <path\n d=\"M20 5.535V2a1 1 0 0 1 2 0v6a1 1 0 0 1-1 1h-6a1 1 0 0 1 0-2h3.638l-2.975-2.653a8 8 0 1 0 1.884 8.32 1 1 0 1 1 1.886.666A10 10 0 1 1 5.175 1.245c3.901-2.15 8.754-1.462 11.88 1.667L20 5.535z\"\n fill=\"#FFF\"\n fill-rule=\"nonzero\"\n />\n</svg>\n<svg\n *ngIf=\"icon === 'close'\"\n data-testid=\"close\"\n width=\"28\"\n height=\"28\"\n viewBox=\"0 0 28 28\"\n xmlns=\"http://www.w3.org/2000/svg\"\n xmlns:xlink=\"http://www.w3.org/1999/xlink\"\n>\n <defs>\n <path\n d=\"M465 5c5.53 0 10 4.47 10 10s-4.47 10-10 10-10-4.47-10-10 4.47-10 10-10zm3.59 5L465 13.59 461.41 10 460 11.41l3.59 3.59-3.59 3.59 1.41 1.41 3.59-3.59 3.59 3.59 1.41-1.41-3.59-3.59 3.59-3.59-1.41-1.41z\"\n id=\"b\"\n />\n <filter\n x=\"-30%\"\n y=\"-30%\"\n width=\"160%\"\n height=\"160%\"\n filterUnits=\"objectBoundingBox\"\n id=\"a\"\n >\n <feOffset in=\"SourceAlpha\" result=\"shadowOffsetOuter1\" />\n <feGaussianBlur\n stdDeviation=\"2\"\n in=\"shadowOffsetOuter1\"\n result=\"shadowBlurOuter1\"\n />\n <feColorMatrix\n values=\"0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.5 0\"\n in=\"shadowBlurOuter1\"\n />\n </filter>\n </defs>\n <g transform=\"translate(-451 -1)\" fill-rule=\"nonzero\" fill=\"none\">\n <use fill=\"#000\" filter=\"url(#a)\" xlink:href=\"#b\" />\n <use fill=\"#FFF\" fill-rule=\"evenodd\" xlink:href=\"#b\" />\n </g>\n</svg>\n<svg\n *ngIf=\"icon === 'file'\"\n data-testid=\"file\"\n className=\"rfu-file-icon--small fa-file-fallback\"\n [attr.height]=\"size || 20\"\n [attr.width]=\"size || 20\"\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 384 512\"\n>\n <path\n d=\"M369.9 97.9L286 14C277 5 264.8-.1 252.1-.1H48C21.5 0 0 21.5 0 48v416c0 26.5 21.5 48 48 48h288c26.5 0 48-21.5 48-48V131.9c0-12.7-5.1-25-14.1-34zM332.1 128H256V51.9l76.1 76.1zM48 464V48h160v104c0 13.3 10.7 24 24 24h104v288H48z\"\n fill=\"#414D54\"\n />\n</svg>\n", directives: [{ type: i5.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i4.TranslateDirective, selector: "[translate],[ngx-translate]", inputs: ["translate", "translateParams"] }] });
1073
+ IconComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.5", type: IconComponent, selector: "stream-icon", inputs: { icon: "icon", size: "size" }, ngImport: i0, template: "<svg\n data-testid=\"action-icon\"\n *ngIf=\"icon === 'action-icon'\"\n height=\"4\"\n viewBox=\"0 0 11 4\"\n width=\"11\"\n xmlns=\"http://www.w3.org/2000/svg\"\n>\n <path\n d=\"M1.5 3a1.5 1.5 0 1 1 0-3 1.5 1.5 0 0 1 0 3zm4 0a1.5 1.5 0 1 1 0-3 1.5 1.5 0 0 1 0 3zm4 0a1.5 1.5 0 1 1 0-3 1.5 1.5 0 0 1 0 3z\"\n fillRule=\"nonzero\"\n />\n</svg>\n<svg\n *ngIf=\"icon === 'delivered-icon'\"\n height=\"16\"\n width=\"16\"\n xmlns=\"http://www.w3.org/2000/svg\"\n data-testid=\"delivered-icon\"\n>\n <path\n d=\"M8 0a8 8 0 1 1 0 16A8 8 0 0 1 8 0zm3.72 6.633a.955.955 0 1 0-1.352-1.352L6.986 8.663 5.633 7.31A.956.956 0 1 0 4.28 8.663l2.029 2.028a.956.956 0 0 0 1.353 0l4.058-4.058z\"\n fill=\"#006CFF\"\n fillRule=\"evenodd\"\n />\n</svg>\n<svg\n *ngIf=\"icon === 'reaction-icon'\"\n height=\"12\"\n viewBox=\"0 0 12 12\"\n width=\"12\"\n xmlns=\"http://www.w3.org/2000/svg\"\n data-testid=\"reaction-icon\"\n>\n <g clipRule=\"evenodd\" fillRule=\"evenodd\">\n <path\n d=\"M6 1.2C3.3 1.2 1.2 3.3 1.2 6c0 2.7 2.1 4.8 4.8 4.8 2.7 0 4.8-2.1 4.8-4.8 0-2.7-2.1-4.8-4.8-4.8zM0 6c0-3.3 2.7-6 6-6s6 2.7 6 6-2.7 6-6 6-6-2.7-6-6z\"\n ></path>\n <path\n d=\"M5.4 4.5c0 .5-.4.9-.9.9s-.9-.4-.9-.9.4-.9.9-.9.9.4.9.9zM8.4 4.5c0 .5-.4.9-.9.9s-.9-.4-.9-.9.4-.9.9-.9.9.4.9.9zM3.3 6.7c.3-.2.6-.1.8.1.3.4.8.9 1.5 1 .6.2 1.4.1 2.4-1 .2-.2.6-.3.8 0 .2.2.3.6 0 .8-1.1 1.3-2.4 1.7-3.5 1.5-1-.2-1.8-.9-2.2-1.5-.2-.3-.1-.7.2-.9z\"\n ></path>\n </g>\n</svg>\n<svg\n data-testid=\"connection-error\"\n *ngIf=\"icon === 'connection-error'\"\n width=\"78px\"\n height=\"78px\"\n viewBox=\"0 0 78 78\"\n version=\"1.1\"\n xmlns=\"http://www.w3.org/2000/svg\"\n xmlns:xlink=\"http://www.w3.org/1999/xlink\"\n>\n <!-- Generator: Sketch 52.6 (67491) - http://www.bohemiancoding.com/sketch -->\n <title>Combined Shape</title>\n <desc>Created with Sketch.</desc>\n <g\n id=\"Interactions\"\n stroke=\"none\"\n stroke-width=\"1\"\n fill=\"none\"\n fill-rule=\"evenodd\"\n >\n <g\n id=\"Connection-Error-_-Connectivity\"\n transform=\"translate(-270.000000, -30.000000)\"\n fill=\"#CF1F25\"\n >\n <g\n id=\"109-network-connection\"\n transform=\"translate(270.000000, 30.000000)\"\n >\n <path\n d=\"M66.4609744,11.414231 C81.6225232,26.5757798 81.6225232,51.157545 66.4609744,66.3188467 C51.2994256,81.4803954 26.7176604,81.4803954 11.5563587,66.3188467 C-3.60519004,51.1572979 -3.60519004,26.5755327 11.5563587,11.414231 C26.7179075,-3.74731776 51.2996727,-3.74731776 66.4609744,11.414231 Z M54.7853215,45.8823776 L54.7853215,40.5882574 C54.7853215,39.613638 53.9952341,38.8235506 53.0206147,38.8235506 L44.9576695,38.8235506 L41.428256,42.3529641 L51.255555,42.3529641 L51.255555,45.8823776 L54.7853215,45.8823776 Z M40.6659027,43.1153174 L37.8988425,45.8823776 L40.6659027,45.8823776 L40.6659027,43.1153174 Z M51.1764962,56.4702653 L58.2353232,56.4702653 C59.2099355,56.4702653 60.00003,55.6801708 60.00003,54.7055585 L60.00003,51.176145 C60.00003,50.2015327 59.2099355,49.4114382 58.2353232,49.4114382 L51.1764962,49.4114382 C50.2018839,49.4114382 49.4117894,50.2015327 49.4117894,51.176145 L49.4117894,54.7055585 C49.4117894,55.6801708 50.2018839,56.4702653 51.1764962,56.4702653 Z M35.2941353,56.4702653 L42.3529624,56.4702653 C43.3275746,56.4702653 44.1176691,55.6801708 44.1176691,54.7055585 L44.1176691,51.176145 C44.1176691,50.2015327 43.3275746,49.4114382 42.3529624,49.4114382 L35.2941353,49.4114382 C34.319523,49.4114382 33.5294285,50.2015327 33.5294285,51.176145 L33.5294285,54.7055585 C33.5294285,55.6801708 34.319523,56.4702653 35.2941353,56.4702653 Z M56.6964989,19.0874231 C56.007381,18.3985134 54.8903216,18.3985134 54.2012036,19.087423 L45.882376,27.4062507 L45.882376,19.4117761 C45.882376,18.4371568 45.0922885,17.6470693 44.1176692,17.6470693 L33.5294286,17.6470693 C32.5548092,17.6470694 31.7647218,18.4371568 31.7647218,19.4117761 L31.7647218,30.0000167 C31.7647219,30.9746363 32.5548092,31.7647237 33.5294285,31.7647237 L41.5239031,31.7647237 L34.4650761,38.8235508 L24.7058947,38.8235508 C23.7312753,38.8235508 22.9411879,39.6136382 22.9411879,40.5882575 L22.9411879,45.8823778 L26.4706014,45.8823778 L26.4706014,42.3529643 L30.9356624,42.3529643 L23.8768354,49.4117914 L19.4117743,49.4117914 C18.4371549,49.4117914 17.6470675,50.2018788 17.6470675,51.1764981 L17.6470675,54.7059117 C17.6504049,54.9674302 17.7129076,55.2248042 17.8298886,55.4587302 L16.4456526,56.8429662 C15.7446193,57.5200453 15.7252005,58.6372282 16.4022825,59.3382615 C17.0793616,60.0392948 18.1965445,60.0587136 18.8975778,59.3816316 C18.9122847,59.3674273 18.9267436,59.3529684 18.940948,59.3382615 L56.6964963,21.5830662 C57.3856425,20.8939094 57.3856425,19.7765747 56.6964963,19.0874179 Z\"\n id=\"Combined-Shape\"\n ></path>\n </g>\n </g>\n </g>\n</svg>\n<svg\n *ngIf=\"icon === 'send'\"\n data-testid=\"send\"\n height=\"17\"\n viewBox=\"0 0 18 17\"\n width=\"18\"\n xmlns=\"http://www.w3.org/2000/svg\"\n>\n <title translate>streamChat.Send</title>\n <path\n d=\"M0 17.015l17.333-8.508L0 0v6.617l12.417 1.89L0 10.397z\"\n fill=\"#006cff\"\n fillRule=\"evenodd\"\n />\n</svg>\n<svg\n *ngIf=\"icon === 'file-upload'\"\n data-testid=\"file-upload\"\n height=\"14\"\n width=\"14\"\n xmlns=\"http://www.w3.org/2000/svg\"\n>\n <title translate>streamChat.Attach files</title>\n <path\n d=\"M1.667.333h10.666c.737 0 1.334.597 1.334 1.334v10.666c0 .737-.597 1.334-1.334 1.334H1.667a1.333 1.333 0 0 1-1.334-1.334V1.667C.333.93.93.333 1.667.333zm2 1.334a1.667 1.667 0 1 0 0 3.333 1.667 1.667 0 0 0 0-3.333zm-2 9.333v1.333h10.666v-4l-2-2-4 4-2-2L1.667 11z\"\n fillRule=\"nonzero\"\n />\n</svg>\n<svg\n data-testid=\"retry\"\n *ngIf=\"icon === 'retry'\"\n width=\"22\"\n height=\"20\"\n viewBox=\"0 0 22 20\"\n xmlns=\"http://www.w3.org/2000/svg\"\n>\n <path\n d=\"M20 5.535V2a1 1 0 0 1 2 0v6a1 1 0 0 1-1 1h-6a1 1 0 0 1 0-2h3.638l-2.975-2.653a8 8 0 1 0 1.884 8.32 1 1 0 1 1 1.886.666A10 10 0 1 1 5.175 1.245c3.901-2.15 8.754-1.462 11.88 1.667L20 5.535z\"\n fill=\"#FFF\"\n fill-rule=\"nonzero\"\n />\n</svg>\n<svg\n *ngIf=\"icon === 'close'\"\n data-testid=\"close\"\n width=\"28\"\n height=\"28\"\n viewBox=\"0 0 28 28\"\n xmlns=\"http://www.w3.org/2000/svg\"\n xmlns:xlink=\"http://www.w3.org/1999/xlink\"\n>\n <defs>\n <path\n d=\"M465 5c5.53 0 10 4.47 10 10s-4.47 10-10 10-10-4.47-10-10 4.47-10 10-10zm3.59 5L465 13.59 461.41 10 460 11.41l3.59 3.59-3.59 3.59 1.41 1.41 3.59-3.59 3.59 3.59 1.41-1.41-3.59-3.59 3.59-3.59-1.41-1.41z\"\n id=\"b\"\n />\n <filter\n x=\"-30%\"\n y=\"-30%\"\n width=\"160%\"\n height=\"160%\"\n filterUnits=\"objectBoundingBox\"\n id=\"a\"\n >\n <feOffset in=\"SourceAlpha\" result=\"shadowOffsetOuter1\" />\n <feGaussianBlur\n stdDeviation=\"2\"\n in=\"shadowOffsetOuter1\"\n result=\"shadowBlurOuter1\"\n />\n <feColorMatrix\n values=\"0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.5 0\"\n in=\"shadowBlurOuter1\"\n />\n </filter>\n </defs>\n <g transform=\"translate(-451 -1)\" fill-rule=\"nonzero\" fill=\"none\">\n <use fill=\"#000\" filter=\"url(#a)\" xlink:href=\"#b\" />\n <use fill=\"#FFF\" fill-rule=\"evenodd\" xlink:href=\"#b\" />\n </g>\n</svg>\n<svg\n *ngIf=\"icon === 'file'\"\n data-testid=\"file\"\n className=\"rfu-file-icon--small fa-file-fallback\"\n [attr.height]=\"size || 20\"\n [attr.width]=\"size || 20\"\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 384 512\"\n>\n <path\n d=\"M369.9 97.9L286 14C277 5 264.8-.1 252.1-.1H48C21.5 0 0 21.5 0 48v416c0 26.5 21.5 48 48 48h288c26.5 0 48-21.5 48-48V131.9c0-12.7-5.1-25-14.1-34zM332.1 128H256V51.9l76.1 76.1zM48 464V48h160v104c0 13.3 10.7 24 24 24h104v288H48z\"\n fill=\"#414D54\"\n />\n</svg>\n", directives: [{ type: i5.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i1.TranslateDirective, selector: "[translate],[ngx-translate]", inputs: ["translate", "translateParams"] }] });
817
1074
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: IconComponent, decorators: [{
818
1075
  type: Component,
819
1076
  args: [{
@@ -833,29 +1090,408 @@ class LoadingIndicatorComponent {
833
1090
  this.color = '#006CFF';
834
1091
  }
835
1092
  }
836
- LoadingIndicatorComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: LoadingIndicatorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
837
- LoadingIndicatorComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.5", type: LoadingIndicatorComponent, selector: "stream-loading-indicator", inputs: { size: "size", color: "color" }, ngImport: i0, template: "<div class=\"str-chat__loading-indicator\">\n <svg\n [attr.height]=\"size\"\n viewBox=\"0 0 30 30\"\n [attr.width]=\"size\"\n data-testid=\"loading-indicator\"\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <defs>\n <linearGradient id=\"a\" x1=\"50%\" x2=\"50%\" y1=\"0%\" y2=\"100%\">\n <stop offset=\"0%\" stop-color=\"#FFF\" stop-opacity=\"0\" />\n <stop\n data-testid=\"stop-color\"\n offset=\"100%\"\n [attr.stop-color]=\"color\"\n stop-opacity=\"1\"\n [ngStyle]=\"{ stopColor: color }\"\n />\n </linearGradient>\n </defs>\n <path\n d=\"M2.518 23.321l1.664-1.11A12.988 12.988 0 0 0 15 28c7.18 0 13-5.82 13-13S22.18 2 15 2V0c8.284 0 15 6.716 15 15 0 8.284-6.716 15-15 15-5.206 0-9.792-2.652-12.482-6.679z\"\n fill=\"url(#a)\"\n fillRule=\"evenodd\"\n />\n </svg>\n</div>\n", directives: [{ type: i5.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }] });
838
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: LoadingIndicatorComponent, decorators: [{
1093
+ LoadingIndicatorComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: LoadingIndicatorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1094
+ LoadingIndicatorComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.5", type: LoadingIndicatorComponent, selector: "stream-loading-indicator", inputs: { size: "size", color: "color" }, ngImport: i0, template: "<div class=\"str-chat__loading-indicator\">\n <svg\n [attr.height]=\"size\"\n viewBox=\"0 0 30 30\"\n [attr.width]=\"size\"\n data-testid=\"loading-indicator\"\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <defs>\n <linearGradient id=\"a\" x1=\"50%\" x2=\"50%\" y1=\"0%\" y2=\"100%\">\n <stop offset=\"0%\" stop-color=\"#FFF\" stop-opacity=\"0\" />\n <stop\n data-testid=\"stop-color\"\n offset=\"100%\"\n [attr.stop-color]=\"color\"\n stop-opacity=\"1\"\n [ngStyle]=\"{ stopColor: color }\"\n />\n </linearGradient>\n </defs>\n <path\n d=\"M2.518 23.321l1.664-1.11A12.988 12.988 0 0 0 15 28c7.18 0 13-5.82 13-13S22.18 2 15 2V0c8.284 0 15 6.716 15 15 0 8.284-6.716 15-15 15-5.206 0-9.792-2.652-12.482-6.679z\"\n fill=\"url(#a)\"\n fillRule=\"evenodd\"\n />\n </svg>\n</div>\n", directives: [{ type: i5.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }] });
1095
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: LoadingIndicatorComponent, decorators: [{
1096
+ type: Component,
1097
+ args: [{
1098
+ selector: 'stream-loading-indicator',
1099
+ templateUrl: './loading-indicator.component.html',
1100
+ styles: [],
1101
+ }]
1102
+ }], ctorParameters: function () { return []; }, propDecorators: { size: [{
1103
+ type: Input
1104
+ }], color: [{
1105
+ type: Input
1106
+ }] } });
1107
+
1108
+ const textareaInjectionToken = new InjectionToken('textareaInjectionToken');
1109
+
1110
+ class TextareaDirective {
1111
+ constructor(viewContainerRef) {
1112
+ this.viewContainerRef = viewContainerRef;
1113
+ this.value = '';
1114
+ this.valueChange = new EventEmitter();
1115
+ this.send = new EventEmitter();
1116
+ this.userMentions = new EventEmitter();
1117
+ this.subscriptions = [];
1118
+ }
1119
+ ngOnChanges(changes) {
1120
+ if (!this.componentRef) {
1121
+ return;
1122
+ }
1123
+ if (changes.componentRef) {
1124
+ this.subscriptions.forEach((s) => s.unsubscribe());
1125
+ if (this.componentRef) {
1126
+ this.subscriptions.push(this.componentRef.instance.valueChange.subscribe((value) => this.valueChange.next(value)));
1127
+ this.subscriptions.push(this.componentRef.instance.send.subscribe((value) => this.send.next(value)));
1128
+ if (this.componentRef.instance.userMentions) {
1129
+ this.subscriptions.push(this.componentRef.instance.userMentions.subscribe((value) => this.userMentions.next(value)));
1130
+ }
1131
+ }
1132
+ }
1133
+ if (changes.areMentionsEnabled) {
1134
+ this.componentRef.instance.areMentionsEnabled = this.areMentionsEnabled;
1135
+ }
1136
+ if (changes.mentionAutocompleteItemTemplate) {
1137
+ this.componentRef.instance.mentionAutocompleteItemTemplate =
1138
+ this.mentionAutocompleteItemTemplate;
1139
+ }
1140
+ if (changes.mentionScope) {
1141
+ this.componentRef.instance.mentionScope = this.mentionScope;
1142
+ }
1143
+ if (changes.value) {
1144
+ this.componentRef.instance.value = this.value;
1145
+ }
1146
+ // ngOnChanges not called for dynamic components since we don't use template binding
1147
+ // eslint-disable-next-line @angular-eslint/no-lifecycle-call
1148
+ this.componentRef.instance.ngOnChanges(changes);
1149
+ }
1150
+ }
1151
+ TextareaDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: TextareaDirective, deps: [{ token: i0.ViewContainerRef }], target: i0.ɵɵFactoryTarget.Directive });
1152
+ TextareaDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "12.2.5", type: TextareaDirective, selector: "[streamTextarea]", inputs: { componentRef: "componentRef", areMentionsEnabled: "areMentionsEnabled", mentionAutocompleteItemTemplate: "mentionAutocompleteItemTemplate", mentionScope: "mentionScope", value: "value" }, outputs: { valueChange: "valueChange", send: "send", userMentions: "userMentions" }, usesOnChanges: true, ngImport: i0 });
1153
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: TextareaDirective, decorators: [{
1154
+ type: Directive,
1155
+ args: [{
1156
+ selector: '[streamTextarea]',
1157
+ }]
1158
+ }], ctorParameters: function () { return [{ type: i0.ViewContainerRef }]; }, propDecorators: { componentRef: [{
1159
+ type: Input
1160
+ }], areMentionsEnabled: [{
1161
+ type: Input
1162
+ }], mentionAutocompleteItemTemplate: [{
1163
+ type: Input
1164
+ }], mentionScope: [{
1165
+ type: Input
1166
+ }], value: [{
1167
+ type: Input
1168
+ }], valueChange: [{
1169
+ type: Output
1170
+ }], send: [{
1171
+ type: Output
1172
+ }], userMentions: [{
1173
+ type: Output
1174
+ }] } });
1175
+
1176
+ class MessageInputConfigService {
1177
+ constructor() {
1178
+ this.isFileUploadEnabled = true;
1179
+ this.areMentionsEnabled = true;
1180
+ this.isMultipleFileUploadEnabled = true;
1181
+ this.mentionScope = 'channel';
1182
+ }
1183
+ }
1184
+ MessageInputConfigService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: MessageInputConfigService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
1185
+ MessageInputConfigService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: MessageInputConfigService, providedIn: 'root' });
1186
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: MessageInputConfigService, decorators: [{
1187
+ type: Injectable,
1188
+ args: [{
1189
+ providedIn: 'root',
1190
+ }]
1191
+ }], ctorParameters: function () { return []; } });
1192
+
1193
+ class AttachmentPreviewListComponent {
1194
+ constructor(attachmentService) {
1195
+ this.attachmentService = attachmentService;
1196
+ this.attachmentUploads$ = this.attachmentService.attachmentUploads$;
1197
+ }
1198
+ retryAttachmentUpload(file) {
1199
+ return __awaiter(this, void 0, void 0, function* () {
1200
+ yield this.attachmentService.retryAttachmentUpload(file);
1201
+ });
1202
+ }
1203
+ deleteAttachment(upload) {
1204
+ return __awaiter(this, void 0, void 0, function* () {
1205
+ yield this.attachmentService.deleteAttachment(upload);
1206
+ });
1207
+ }
1208
+ trackByFile(_, item) {
1209
+ return item.file;
1210
+ }
1211
+ }
1212
+ AttachmentPreviewListComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: AttachmentPreviewListComponent, deps: [{ token: AttachmentService }], target: i0.ɵɵFactoryTarget.Component });
1213
+ AttachmentPreviewListComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.5", type: AttachmentPreviewListComponent, selector: "stream-attachment-preview-list", ngImport: i0, template: "<div class=\"rfu-image-previewer\">\n <ng-container\n *ngFor=\"\n let attachmentUpload of attachmentUploads$ | async;\n trackBy: trackByFile\n \"\n >\n <div\n *ngIf=\"attachmentUpload.type === 'image'\"\n class=\"rfu-image-previewer__image\"\n [class.rfu-image-previewer__image--loaded]=\"\n attachmentUpload.state === 'success'\n \"\n data-testclass=\"attachment-image-preview\"\n >\n <div\n *ngIf=\"attachmentUpload.state === 'error'\"\n class=\"rfu-image-previewer__retry\"\n (click)=\"retryAttachmentUpload(attachmentUpload.file)\"\n (keyup.enter)=\"retryAttachmentUpload(attachmentUpload.file)\"\n data-testclass=\"upload-error\"\n >\n <stream-icon icon=\"retry\"></stream-icon>\n </div>\n <div class=\"rfu-thumbnail__wrapper\" style=\"width: 100; height: 100\">\n <div class=\"rfu-thumbnail__overlay\">\n <div\n class=\"rfu-icon-button\"\n data-testclass=\"delete-attachment\"\n role=\"button\"\n (click)=\"deleteAttachment(attachmentUpload)\"\n (keyup.enter)=\"deleteAttachment(attachmentUpload)\"\n >\n <stream-icon icon=\"close\"></stream-icon>\n </div>\n </div>\n <img\n *ngIf=\"attachmentUpload.url || attachmentUpload.previewUri\"\n src=\"{{\n attachmentUpload.url\n ? attachmentUpload.url\n : attachmentUpload.previewUri\n }}\"\n alt=\"attachmentUpload.file.name\"\n class=\"rfu-thumbnail__image\"\n data-testclass=\"attachment-image\"\n />\n </div>\n <stream-loading-indicator\n data-testclass=\"loading-indicator\"\n color=\"rgba(255,255,255,0.7)\"\n *ngIf=\"attachmentUpload.state === 'uploading'\"\n ></stream-loading-indicator>\n </div>\n <div\n class=\"rfu-file-previewer\"\n *ngIf=\"attachmentUpload.type === 'file'\"\n data-testclass=\"attachment-file-preview\"\n >\n <ol>\n <li\n class=\"rfu-file-previewer__file\"\n [class.rfu-file-previewer__file--uploading]=\"\n attachmentUpload.state === 'uploading'\n \"\n [class.rfu-file-previewer__file--failed]=\"\n attachmentUpload.state === 'error'\n \"\n >\n <stream-icon icon=\"file\"></stream-icon>\n\n <a\n data-testclass=\"file-download-link\"\n href=\"{{ attachmentUpload.url }}\"\n (click)=\"attachmentUpload.url ? null : $event.preventDefault()\"\n (keyup.enter)=\"\n attachmentUpload.url ? null : $event.preventDefault()\n \"\n download\n >\n {{ attachmentUpload.file.name }}\n <ng-container *ngIf=\"attachmentUpload.state === 'error'\">\n <div\n data-testclass=\"file-upload-retry\"\n class=\"rfu-file-previewer__failed\"\n (click)=\"retryAttachmentUpload(attachmentUpload.file)\"\n (keyup.enter)=\"retryAttachmentUpload(attachmentUpload.file)\"\n translate\n >\n streamChat.failed\n </div>\n <div\n class=\"rfu-file-previewer__retry\"\n (click)=\"retryAttachmentUpload(attachmentUpload.file)\"\n (keyup.enter)=\"retryAttachmentUpload(attachmentUpload.file)\"\n translate\n >\n streamChat.retry\n </div>\n </ng-container>\n </a>\n\n <span\n data-testclass=\"file-delete\"\n class=\"rfu-file-previewer__close-button\"\n (click)=\"deleteAttachment(attachmentUpload)\"\n (keyup.enter)=\"deleteAttachment(attachmentUpload)\"\n >\n \u2718\n </span>\n <div\n *ngIf=\"attachmentUpload.state === 'uploading'\"\n class=\"rfu-file-previewer__loading-indicator\"\n >\n <stream-loading-indicator></stream-loading-indicator>\n </div>\n </li>\n </ol>\n </div>\n </ng-container>\n</div>\n", components: [{ type: IconComponent, selector: "stream-icon", inputs: ["icon", "size"] }, { type: LoadingIndicatorComponent, selector: "stream-loading-indicator", inputs: ["size", "color"] }], directives: [{ type: i5.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i5.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i1.TranslateDirective, selector: "[translate],[ngx-translate]", inputs: ["translate", "translateParams"] }], pipes: { "async": i5.AsyncPipe } });
1214
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: AttachmentPreviewListComponent, decorators: [{
1215
+ type: Component,
1216
+ args: [{
1217
+ selector: 'stream-attachment-preview-list',
1218
+ templateUrl: './attachment-preview-list.component.html',
1219
+ styles: [],
1220
+ }]
1221
+ }], ctorParameters: function () { return [{ type: AttachmentService }]; } });
1222
+
1223
+ class MessageInputComponent {
1224
+ constructor(channelService, notificationService, attachmentService, configService, textareaType, componentFactoryResolver) {
1225
+ this.channelService = channelService;
1226
+ this.notificationService = notificationService;
1227
+ this.attachmentService = attachmentService;
1228
+ this.configService = configService;
1229
+ this.textareaType = textareaType;
1230
+ this.componentFactoryResolver = componentFactoryResolver;
1231
+ this.messageUpdate = new EventEmitter();
1232
+ this.textareaValue = '';
1233
+ this.mentionedUsers = [];
1234
+ this.subscriptions = [];
1235
+ this.subscriptions.push(this.channelService.activeChannel$.subscribe((channel) => {
1236
+ var _a;
1237
+ this.textareaValue = '';
1238
+ this.attachmentService.resetAttachmentUploads();
1239
+ const capabilities = (_a = channel === null || channel === void 0 ? void 0 : channel.data) === null || _a === void 0 ? void 0 : _a.own_capabilities;
1240
+ if (capabilities) {
1241
+ this.isFileUploadAuthorized =
1242
+ capabilities.indexOf('upload-file') !== -1;
1243
+ }
1244
+ }));
1245
+ this.subscriptions.push(this.attachmentService.attachmentUploadInProgressCounter$.subscribe((counter) => {
1246
+ if (counter === 0 && this.hideNotification) {
1247
+ this.hideNotification();
1248
+ this.hideNotification = undefined;
1249
+ }
1250
+ }));
1251
+ this.attachmentUploads$ = this.attachmentService.attachmentUploads$;
1252
+ this.isFileUploadEnabled = this.configService.isFileUploadEnabled;
1253
+ this.acceptedFileTypes = this.configService.acceptedFileTypes;
1254
+ this.isMultipleFileUploadEnabled =
1255
+ this.configService.isMultipleFileUploadEnabled;
1256
+ this.areMentionsEnabled = this.configService.areMentionsEnabled;
1257
+ this.mentionAutocompleteItemTemplate =
1258
+ this.configService.mentionAutocompleteItemTemplate;
1259
+ this.mentionScope = this.configService.mentionScope;
1260
+ }
1261
+ ngOnInit() {
1262
+ const componentFactory = this.componentFactoryResolver.resolveComponentFactory(this.textareaType);
1263
+ this.textareaRef =
1264
+ this.textareaAnchor.viewContainerRef.createComponent(componentFactory);
1265
+ }
1266
+ ngOnChanges(changes) {
1267
+ if (changes.message) {
1268
+ this.attachmentService.resetAttachmentUploads();
1269
+ if (this.isUpdate) {
1270
+ this.attachmentService.createFromAttachments(this.message.attachments || []);
1271
+ this.textareaValue = this.message.text || '';
1272
+ }
1273
+ }
1274
+ if (changes.isFileUploadEnabled) {
1275
+ this.configService.isFileUploadEnabled = this.isFileUploadEnabled;
1276
+ }
1277
+ if (changes.acceptedFileTypes) {
1278
+ this.configService.acceptedFileTypes = this.acceptedFileTypes;
1279
+ }
1280
+ if (changes.isMultipleFileUploadEnabled) {
1281
+ this.configService.isMultipleFileUploadEnabled =
1282
+ this.isMultipleFileUploadEnabled;
1283
+ }
1284
+ if (changes.areMentionsEnabled) {
1285
+ this.configService.areMentionsEnabled = this.areMentionsEnabled;
1286
+ }
1287
+ if (changes.mentionAutocompleteItemTemplate) {
1288
+ this.configService.mentionAutocompleteItemTemplate =
1289
+ this.mentionAutocompleteItemTemplate;
1290
+ }
1291
+ if (changes.mentionScope) {
1292
+ this.configService.mentionScope = this.mentionScope;
1293
+ }
1294
+ }
1295
+ ngOnDestroy() {
1296
+ this.subscriptions.forEach((s) => s.unsubscribe());
1297
+ }
1298
+ messageSent() {
1299
+ return __awaiter(this, void 0, void 0, function* () {
1300
+ let attachmentUploadInProgressCounter;
1301
+ this.attachmentService.attachmentUploadInProgressCounter$
1302
+ .pipe(first())
1303
+ .subscribe((counter) => (attachmentUploadInProgressCounter = counter));
1304
+ if (attachmentUploadInProgressCounter > 0) {
1305
+ if (!this.hideNotification) {
1306
+ this.hideNotification =
1307
+ this.notificationService.addPermanentNotification('streamChat.Wait until all attachments have uploaded');
1308
+ }
1309
+ return;
1310
+ }
1311
+ const attachments = this.attachmentService.mapToAttachments();
1312
+ const text = this.textareaValue;
1313
+ if (!text && (!attachments || attachments.length === 0)) {
1314
+ return;
1315
+ }
1316
+ if (!this.isUpdate) {
1317
+ this.textareaValue = '';
1318
+ }
1319
+ try {
1320
+ yield (this.isUpdate
1321
+ ? this.channelService.updateMessage(Object.assign(Object.assign({}, this.message), { text: text, attachments: attachments }))
1322
+ : this.channelService.sendMessage(text, attachments, this.mentionedUsers));
1323
+ this.messageUpdate.emit();
1324
+ if (!this.isUpdate) {
1325
+ this.attachmentService.resetAttachmentUploads();
1326
+ }
1327
+ }
1328
+ catch (error) {
1329
+ if (this.isUpdate) {
1330
+ this.notificationService.addTemporaryNotification('streamChat.Edit message request failed');
1331
+ }
1332
+ }
1333
+ });
1334
+ }
1335
+ get accept() {
1336
+ var _a;
1337
+ return this.acceptedFileTypes ? (_a = this.acceptedFileTypes) === null || _a === void 0 ? void 0 : _a.join(',') : '';
1338
+ }
1339
+ filesSelected(fileList) {
1340
+ return __awaiter(this, void 0, void 0, function* () {
1341
+ yield this.attachmentService.filesSelected(fileList);
1342
+ this.clearFileInput();
1343
+ });
1344
+ }
1345
+ clearFileInput() {
1346
+ this.fileInput.nativeElement.value = '';
1347
+ }
1348
+ get isUpdate() {
1349
+ return !!this.message;
1350
+ }
1351
+ }
1352
+ MessageInputComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: MessageInputComponent, deps: [{ token: ChannelService }, { token: NotificationService }, { token: AttachmentService }, { token: MessageInputConfigService }, { token: textareaInjectionToken }, { token: i0.ComponentFactoryResolver }], target: i0.ɵɵFactoryTarget.Component });
1353
+ MessageInputComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.5", type: MessageInputComponent, selector: "stream-message-input", inputs: { isFileUploadEnabled: "isFileUploadEnabled", areMentionsEnabled: "areMentionsEnabled", mentionScope: "mentionScope", mentionAutocompleteItemTemplate: "mentionAutocompleteItemTemplate", acceptedFileTypes: "acceptedFileTypes", isMultipleFileUploadEnabled: "isMultipleFileUploadEnabled", message: "message" }, outputs: { messageUpdate: "messageUpdate" }, providers: [AttachmentService], viewQueries: [{ propertyName: "fileInput", first: true, predicate: ["fileInput"], descendants: true }, { propertyName: "textareaAnchor", first: true, predicate: TextareaDirective, descendants: true, static: true }], usesOnChanges: true, ngImport: i0, template: "<div\n class=\"str-chat__input-flat\"\n [class.str-chat__input-flat-has-attachments]=\"\n (attachmentUploads$ | async)!.length > 0\n \"\n>\n <div class=\"str-chat__input-flat-wrapper\">\n <div class=\"str-chat__input-flat--textarea-wrapper\">\n <stream-attachment-preview-list\n class=\"rfu-image-previewer-angular-host\"\n ></stream-attachment-preview-list>\n <div class=\"rta str-chat__textarea\">\n <ng-template\n streamTextarea\n [(value)]=\"textareaValue\"\n (send)=\"messageSent()\"\n [componentRef]=\"textareaRef\"\n (userMentions)=\"mentionedUsers = $event\"\n [areMentionsEnabled]=\"areMentionsEnabled\"\n [mentionAutocompleteItemTemplate]=\"mentionAutocompleteItemTemplate\"\n [mentionScope]=\"mentionScope\"\n ></ng-template>\n </div>\n <div\n *ngIf=\"isFileUploadEnabled && isFileUploadAuthorized\"\n class=\"str-chat__fileupload-wrapper\"\n data-testid=\"file-upload-button\"\n >\n <div class=\"str-chat__tooltip\">\n {{ \"streamChat.Attach files\" | translate }}\n </div>\n <div class=\"rfu-file-upload-button\">\n <label>\n <input\n #fileInput\n type=\"file\"\n class=\"rfu-file-input\"\n data-testid=\"file-input\"\n [accept]=\"accept\"\n [multiple]=\"isMultipleFileUploadEnabled\"\n (change)=\"filesSelected(fileInput.files)\"\n />\n <span class=\"str-chat__input-flat-fileupload\">\n <stream-icon icon=\"file-upload\"></stream-icon>\n </span>\n </label>\n </div>\n </div>\n </div>\n <button\n data-testid=\"send-button\"\n class=\"str-chat__send-button\"\n (click)=\"messageSent()\"\n (keyup.enter)=\"messageSent()\"\n >\n <stream-icon icon=\"send\"></stream-icon>\n </button>\n </div>\n</div>\n", components: [{ type: AttachmentPreviewListComponent, selector: "stream-attachment-preview-list" }, { type: IconComponent, selector: "stream-icon", inputs: ["icon", "size"] }], directives: [{ type: TextareaDirective, selector: "[streamTextarea]", inputs: ["componentRef", "areMentionsEnabled", "mentionAutocompleteItemTemplate", "mentionScope", "value"], outputs: ["valueChange", "send", "userMentions"] }, { type: i5.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }], pipes: { "async": i5.AsyncPipe, "translate": i1.TranslatePipe } });
1354
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: MessageInputComponent, decorators: [{
1355
+ type: Component,
1356
+ args: [{
1357
+ selector: 'stream-message-input',
1358
+ templateUrl: './message-input.component.html',
1359
+ styles: [],
1360
+ providers: [AttachmentService],
1361
+ }]
1362
+ }], ctorParameters: function () { return [{ type: ChannelService }, { type: NotificationService }, { type: AttachmentService }, { type: MessageInputConfigService }, { type: i0.Type, decorators: [{
1363
+ type: Inject,
1364
+ args: [textareaInjectionToken]
1365
+ }] }, { type: i0.ComponentFactoryResolver }]; }, propDecorators: { isFileUploadEnabled: [{
1366
+ type: Input
1367
+ }], areMentionsEnabled: [{
1368
+ type: Input
1369
+ }], mentionScope: [{
1370
+ type: Input
1371
+ }], mentionAutocompleteItemTemplate: [{
1372
+ type: Input
1373
+ }], acceptedFileTypes: [{
1374
+ type: Input
1375
+ }], isMultipleFileUploadEnabled: [{
1376
+ type: Input
1377
+ }], message: [{
1378
+ type: Input
1379
+ }], messageUpdate: [{
1380
+ type: Output
1381
+ }], fileInput: [{
1382
+ type: ViewChild,
1383
+ args: ['fileInput']
1384
+ }], textareaAnchor: [{
1385
+ type: ViewChild,
1386
+ args: [TextareaDirective, { static: true }]
1387
+ }] } });
1388
+
1389
+ class ModalComponent {
1390
+ constructor() {
1391
+ this.isOpen = false;
1392
+ this.isOpenChange = new EventEmitter();
1393
+ this.watchForEscPress = (event) => {
1394
+ if (event.key === 'Escape') {
1395
+ this.close();
1396
+ }
1397
+ };
1398
+ this.stopWatchForEscPress = () => {
1399
+ window.removeEventListener('keyup', this.watchForEscPress);
1400
+ };
1401
+ this.watchForOutsideClicks = (event) => {
1402
+ var _a;
1403
+ if (!((_a = this.content) === null || _a === void 0 ? void 0 : _a.nativeElement.contains(event.target))) {
1404
+ this.close();
1405
+ }
1406
+ };
1407
+ }
1408
+ ngOnChanges(changes) {
1409
+ if (changes.isOpen) {
1410
+ if (this.isOpen) {
1411
+ window.addEventListener('keyup', this.watchForEscPress);
1412
+ setTimeout(() => window.addEventListener('click', this.watchForOutsideClicks), 0);
1413
+ }
1414
+ else {
1415
+ this.stopWatchForOutsideClicks();
1416
+ this.stopWatchForEscPress();
1417
+ }
1418
+ }
1419
+ }
1420
+ close() {
1421
+ this.isOpen = false;
1422
+ this.isOpenChange.emit(false);
1423
+ this.stopWatchForOutsideClicks();
1424
+ this.stopWatchForEscPress();
1425
+ }
1426
+ stopWatchForOutsideClicks() {
1427
+ window.removeEventListener('click', this.watchForOutsideClicks);
1428
+ }
1429
+ }
1430
+ ModalComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: ModalComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1431
+ ModalComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.5", type: ModalComponent, selector: "stream-modal", inputs: { isOpen: "isOpen" }, outputs: { isOpenChange: "isOpenChange" }, viewQueries: [{ propertyName: "content", first: true, predicate: ["content"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div\n data-testid=\"modal\"\n class=\"str-chat__modal str-chat__modal--{{ isOpen ? 'open' : 'close' }}\"\n>\n <div\n data-testid=\"close\"\n class=\"str-chat__modal__close-button\"\n (click)=\"close()\"\n (keyup.enter)=\"close()\"\n translate\n >\n streamChat.Close\n <stream-icon icon=\"close\"></stream-icon>\n </div>\n <div class=\"str-chat__modal__inner\" #content>\n <ng-content></ng-content>\n </div>\n</div>\n", components: [{ type: IconComponent, selector: "stream-icon", inputs: ["icon", "size"] }], directives: [{ type: i1.TranslateDirective, selector: "[translate],[ngx-translate]", inputs: ["translate", "translateParams"] }] });
1432
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: ModalComponent, decorators: [{
1433
+ type: Component,
1434
+ args: [{
1435
+ selector: 'stream-modal',
1436
+ templateUrl: './modal.component.html',
1437
+ styles: [],
1438
+ }]
1439
+ }], ctorParameters: function () { return []; }, propDecorators: { isOpen: [{
1440
+ type: Input
1441
+ }], isOpenChange: [{
1442
+ type: Output
1443
+ }], content: [{
1444
+ type: ViewChild,
1445
+ args: ['content']
1446
+ }] } });
1447
+
1448
+ class NotificationComponent {
1449
+ constructor() { }
1450
+ }
1451
+ NotificationComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: NotificationComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1452
+ NotificationComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.5", type: NotificationComponent, selector: "stream-notification", inputs: { type: "type" }, ngImport: i0, template: "<div\n class=\"str-chat__custom-notification notification-{{ type }}\"\n data-testid=\"custom-notification\"\n>\n <ng-content></ng-content>\n</div>\n" });
1453
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: NotificationComponent, decorators: [{
1454
+ type: Component,
1455
+ args: [{
1456
+ selector: 'stream-notification',
1457
+ templateUrl: './notification.component.html',
1458
+ styles: [],
1459
+ }]
1460
+ }], ctorParameters: function () { return []; }, propDecorators: { type: [{
1461
+ type: Input
1462
+ }] } });
1463
+
1464
+ class NotificationListComponent {
1465
+ constructor(notificationService) {
1466
+ this.notificationService = notificationService;
1467
+ this.notifications$ = this.notificationService.notifications$;
1468
+ }
1469
+ trackByItem(_, item) {
1470
+ return item;
1471
+ }
1472
+ }
1473
+ NotificationListComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: NotificationListComponent, deps: [{ token: NotificationService }], target: i0.ɵɵFactoryTarget.Component });
1474
+ NotificationListComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.5", type: NotificationListComponent, selector: "stream-notification-list", ngImport: i0, template: "<div class=\"str-chat__list-notifications\">\n <stream-notification\n *ngFor=\"let notification of notifications$ | async; trackBy: trackByItem\"\n [type]=\"notification.type\"\n ><div data-testclass=\"notification-content\" translate>\n {{ notification.text }}\n </div></stream-notification\n >\n</div>\n", components: [{ type: NotificationComponent, selector: "stream-notification", inputs: ["type"] }], directives: [{ type: i5.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i1.TranslateDirective, selector: "[translate],[ngx-translate]", inputs: ["translate", "translateParams"] }], pipes: { "async": i5.AsyncPipe } });
1475
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: NotificationListComponent, decorators: [{
839
1476
  type: Component,
840
1477
  args: [{
841
- selector: 'stream-loading-indicator',
842
- templateUrl: './loading-indicator.component.html',
1478
+ selector: 'stream-notification-list',
1479
+ templateUrl: './notification-list.component.html',
843
1480
  styles: [],
844
1481
  }]
845
- }], ctorParameters: function () { return []; }, propDecorators: { size: [{
846
- type: Input
847
- }], color: [{
848
- type: Input
849
- }] } });
1482
+ }], ctorParameters: function () { return [{ type: NotificationService }]; } });
850
1483
 
851
1484
  class MessageActionsBoxComponent {
852
- constructor(chatClientService, notificationService) {
1485
+ constructor(chatClientService, notificationService, channelService) {
853
1486
  this.chatClientService = chatClientService;
854
1487
  this.notificationService = notificationService;
1488
+ this.channelService = channelService;
855
1489
  this.isOpen = false;
856
1490
  this.isMine = false;
857
1491
  this.enabledActions = [];
858
1492
  this.displayedActionsCount = new EventEmitter();
1493
+ this.isEditing = new EventEmitter();
1494
+ this.isEditModalOpen = false;
859
1495
  }
860
1496
  ngOnChanges(changes) {
861
1497
  if (changes.isMine || changes.enabledActions) {
@@ -885,10 +1521,12 @@ class MessageActionsBoxComponent {
885
1521
  return this.enabledActions.indexOf('quote') !== -1;
886
1522
  }
887
1523
  get isEditVisible() {
888
- return this.enabledActions.indexOf('edit') !== -1;
1524
+ return ((this.enabledActions.indexOf('edit') !== -1 && this.isMine) ||
1525
+ this.enabledActions.indexOf('edit-any') !== -1);
889
1526
  }
890
1527
  get isDeleteVisible() {
891
- return this.enabledActions.indexOf('delete') !== -1;
1528
+ return ((this.enabledActions.indexOf('delete') !== -1 && this.isMine) ||
1529
+ this.enabledActions.indexOf('delete-any') !== -1);
892
1530
  }
893
1531
  get isMuteVisible() {
894
1532
  return this.enabledActions.indexOf('mute') !== -1;
@@ -920,14 +1558,30 @@ class MessageActionsBoxComponent {
920
1558
  alert('Feature not yet implemented');
921
1559
  }
922
1560
  editClicked() {
923
- alert('Feature not yet implemented');
1561
+ this.isEditing.emit(true);
1562
+ this.isEditModalOpen = true;
1563
+ }
1564
+ sendClicked() {
1565
+ var _a;
1566
+ (_a = this.messageInput) === null || _a === void 0 ? void 0 : _a.messageSent();
1567
+ }
1568
+ modalClosed() {
1569
+ this.isEditModalOpen = false;
1570
+ this.isEditing.emit(false);
924
1571
  }
925
1572
  deleteClicked() {
926
- alert('Feature not yet implemented');
1573
+ return __awaiter(this, void 0, void 0, function* () {
1574
+ try {
1575
+ yield this.channelService.deleteMessage(this.message);
1576
+ }
1577
+ catch (error) {
1578
+ this.notificationService.addTemporaryNotification('streamChat.Error deleting message');
1579
+ }
1580
+ });
927
1581
  }
928
1582
  }
929
- MessageActionsBoxComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: MessageActionsBoxComponent, deps: [{ token: ChatClientService }, { token: NotificationService }], target: i0.ɵɵFactoryTarget.Component });
930
- MessageActionsBoxComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.5", type: MessageActionsBoxComponent, selector: "stream-message-actions-box", inputs: { isOpen: "isOpen", isMine: "isMine", message: "message", enabledActions: "enabledActions" }, outputs: { displayedActionsCount: "displayedActionsCount" }, usesOnChanges: true, ngImport: i0, template: "<div\n data-testid=\"action-box\"\n class=\"str-chat__message-actions-box\"\n [class.str-chat__message-actions-box--open]=\"isOpen\"\n [class.str-chat__message-actions-box--mine]=\"isMine\"\n>\n <ul class=\"str-chat__message-actions-list\">\n <button\n data-testid=\"quote-action\"\n *ngIf=\"isQuoteVisible\"\n (click)=\"quoteClicked()\"\n >\n <li class=\"str-chat__message-actions-list-item\">\n {{ \"streamChat.Reply\" | translate }}\n </li>\n </button>\n <button\n data-testid=\"pin-action\"\n *ngIf=\"isPinVisible\"\n (click)=\"pinClicked()\"\n >\n <li class=\"str-chat__message-actions-list-item\">\n {{\n (message?.pinned ? \"streamChat.Unpin\" : \"streamChat.Pin\") | translate\n }}\n </li>\n </button>\n <button\n data-testid=\"flag-action\"\n *ngIf=\"isFlagVisible\"\n (click)=\"flagClicked()\"\n >\n <li class=\"str-chat__message-actions-list-item\">\n {{ \"streamChat.Flag\" | translate }}\n </li>\n </button>\n <button\n data-testid=\"mute-action\"\n *ngIf=\"isMuteVisible\"\n (click)=\"muteClicked()\"\n >\n <li class=\"str-chat__message-actions-list-item\">\n {{ \"streamChat.Mute\" | translate }}\n </li>\n </button>\n <button\n data-testid=\"edit-action\"\n *ngIf=\"isEditVisible\"\n (click)=\"editClicked()\"\n >\n <li class=\"str-chat__message-actions-list-item\">\n {{ \"streamChat.Edit Message\" | translate }}\n </li>\n </button>\n <button\n data-testid=\"delete-action\"\n *ngIf=\"isDeleteVisible\"\n (click)=\"deleteClicked()\"\n >\n <li class=\"str-chat__message-actions-list-item\">\n {{ \"streamChat.Delete\" | translate }}\n </li>\n </button>\n </ul>\n</div>\n", directives: [{ type: i5.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }], pipes: { "translate": i4.TranslatePipe } });
1583
+ MessageActionsBoxComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: MessageActionsBoxComponent, deps: [{ token: ChatClientService }, { token: NotificationService }, { token: ChannelService }], target: i0.ɵɵFactoryTarget.Component });
1584
+ MessageActionsBoxComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.5", type: MessageActionsBoxComponent, selector: "stream-message-actions-box", inputs: { isOpen: "isOpen", isMine: "isMine", message: "message", enabledActions: "enabledActions" }, outputs: { displayedActionsCount: "displayedActionsCount", isEditing: "isEditing" }, viewQueries: [{ propertyName: "messageInput", first: true, predicate: MessageInputComponent, descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div\n data-testid=\"action-box\"\n class=\"str-chat__message-actions-box\"\n [class.str-chat__message-actions-box--open]=\"isOpen\"\n [class.str-chat__message-actions-box--mine]=\"isMine\"\n>\n <ul class=\"str-chat__message-actions-list\">\n <button\n data-testid=\"quote-action\"\n *ngIf=\"isQuoteVisible\"\n (click)=\"quoteClicked()\"\n >\n <li class=\"str-chat__message-actions-list-item\">\n {{ \"streamChat.Reply\" | translate }}\n </li>\n </button>\n <button\n data-testid=\"pin-action\"\n *ngIf=\"isPinVisible\"\n (click)=\"pinClicked()\"\n >\n <li class=\"str-chat__message-actions-list-item\">\n {{\n (message?.pinned ? \"streamChat.Unpin\" : \"streamChat.Pin\") | translate\n }}\n </li>\n </button>\n <button\n data-testid=\"flag-action\"\n *ngIf=\"isFlagVisible\"\n (click)=\"flagClicked()\"\n >\n <li class=\"str-chat__message-actions-list-item\">\n {{ \"streamChat.Flag\" | translate }}\n </li>\n </button>\n <button\n data-testid=\"mute-action\"\n *ngIf=\"isMuteVisible\"\n (click)=\"muteClicked()\"\n >\n <li class=\"str-chat__message-actions-list-item\">\n {{ \"streamChat.Mute\" | translate }}\n </li>\n </button>\n <button\n data-testid=\"edit-action\"\n *ngIf=\"isEditVisible\"\n (click)=\"editClicked()\"\n >\n <li class=\"str-chat__message-actions-list-item\">\n {{ \"streamChat.Edit Message\" | translate }}\n </li>\n </button>\n <button\n data-testid=\"delete-action\"\n *ngIf=\"isDeleteVisible\"\n (click)=\"deleteClicked()\"\n >\n <li class=\"str-chat__message-actions-list-item\">\n {{ \"streamChat.Delete\" | translate }}\n </li>\n </button>\n </ul>\n</div>\n\n<stream-modal\n [isOpen]=\"isEditModalOpen\"\n (isOpenChange)=\"\n isEditModalOpen = $event; isEditModalOpen ? '' : modalClosed()\n \"\n>\n <div class=\"str-chat__edit-message-form\" *ngIf=\"isEditModalOpen\">\n <stream-message-input\n [message]=\"message\"\n (messageUpdate)=\"modalClosed()\"\n ></stream-message-input>\n <stream-notification-list></stream-notification-list>\n <div class=\"str-chat__message-team-form-footer\">\n <div></div>\n <div>\n <button translate data-testid=\"cancel-button\" (click)=\"modalClosed()\">\n streamChat.Cancel\n </button>\n <button\n type=\"submit\"\n translate\n data-testid=\"send-button\"\n (click)=\"sendClicked()\"\n (keyup.enter)=\"sendClicked()\"\n >\n streamChat.Send\n </button>\n </div>\n </div>\n </div>\n</stream-modal>\n", components: [{ type: ModalComponent, selector: "stream-modal", inputs: ["isOpen"], outputs: ["isOpenChange"] }, { type: MessageInputComponent, selector: "stream-message-input", inputs: ["isFileUploadEnabled", "areMentionsEnabled", "mentionScope", "mentionAutocompleteItemTemplate", "acceptedFileTypes", "isMultipleFileUploadEnabled", "message"], outputs: ["messageUpdate"] }, { type: NotificationListComponent, selector: "stream-notification-list" }], directives: [{ type: i5.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i1.TranslateDirective, selector: "[translate],[ngx-translate]", inputs: ["translate", "translateParams"] }], pipes: { "translate": i1.TranslatePipe } });
931
1585
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: MessageActionsBoxComponent, decorators: [{
932
1586
  type: Component,
933
1587
  args: [{
@@ -935,7 +1589,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImpor
935
1589
  templateUrl: './message-actions-box.component.html',
936
1590
  styles: [],
937
1591
  }]
938
- }], ctorParameters: function () { return [{ type: ChatClientService }, { type: NotificationService }]; }, propDecorators: { isOpen: [{
1592
+ }], ctorParameters: function () { return [{ type: ChatClientService }, { type: NotificationService }, { type: ChannelService }]; }, propDecorators: { isOpen: [{
939
1593
  type: Input
940
1594
  }], isMine: [{
941
1595
  type: Input
@@ -945,6 +1599,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImpor
945
1599
  type: Input
946
1600
  }], displayedActionsCount: [{
947
1601
  type: Output
1602
+ }], isEditing: [{
1603
+ type: Output
1604
+ }], messageInput: [{
1605
+ type: ViewChild,
1606
+ args: [MessageInputComponent]
948
1607
  }] } });
949
1608
 
950
1609
  class ChannelComponent {
@@ -1047,7 +1706,7 @@ class ChannelHeaderComponent {
1047
1706
  }
1048
1707
  }
1049
1708
  ChannelHeaderComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: ChannelHeaderComponent, deps: [{ token: ChannelService }, { token: ChannelListToggleService }], target: i0.ɵɵFactoryTarget.Component });
1050
- ChannelHeaderComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.5", type: ChannelHeaderComponent, selector: "stream-channel-header", ngImport: i0, template: "<div class=\"str-chat__header-livestream\">\n <div\n class=\"str-chat__header-hamburger\"\n (click)=\"toggleMenu($event)\"\n (keyup.enter)=\"toggleMenu($event)\"\n >\n <span class=\"str-chat__header-hamburger--line\"></span>\n <span class=\"str-chat__header-hamburger--line\"></span>\n <span class=\"str-chat__header-hamburger--line\"></span>\n </div>\n <stream-avatar\n imageUrl=\"{{ activeChannel?.data?.image }}\"\n name=\"{{ activeChannel?.data?.name }}\"\n ></stream-avatar>\n <div class=\"str-chat__header-livestream-left\">\n <p class=\"str-chat__header-livestream-left--title\">\n {{ activeChannel?.data?.name }}\n </p>\n <p class=\"str-chat__header-livestream-left--members\">\n {{'streamChat.{{ memberCount }} members' | translate:memberCountParam}}\n {{'streamChat.{{ watcherCount }} online' | translate:watcherCountParam}}\n </p>\n </div>\n</div>\n", components: [{ type: AvatarComponent, selector: "stream-avatar", inputs: ["name", "imageUrl", "size"] }], pipes: { "translate": i4.TranslatePipe } });
1709
+ ChannelHeaderComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.5", type: ChannelHeaderComponent, selector: "stream-channel-header", ngImport: i0, template: "<div class=\"str-chat__header-livestream\">\n <div\n class=\"str-chat__header-hamburger\"\n (click)=\"toggleMenu($event)\"\n (keyup.enter)=\"toggleMenu($event)\"\n >\n <span class=\"str-chat__header-hamburger--line\"></span>\n <span class=\"str-chat__header-hamburger--line\"></span>\n <span class=\"str-chat__header-hamburger--line\"></span>\n </div>\n <stream-avatar\n imageUrl=\"{{ activeChannel?.data?.image }}\"\n name=\"{{ activeChannel?.data?.name }}\"\n ></stream-avatar>\n <div class=\"str-chat__header-livestream-left\">\n <p class=\"str-chat__header-livestream-left--title\">\n {{ activeChannel?.data?.name }}\n </p>\n <p class=\"str-chat__header-livestream-left--members\">\n {{'streamChat.{{ memberCount }} members' | translate:memberCountParam}}\n {{'streamChat.{{ watcherCount }} online' | translate:watcherCountParam}}\n </p>\n </div>\n</div>\n", components: [{ type: AvatarComponent, selector: "stream-avatar", inputs: ["name", "imageUrl", "size"] }], pipes: { "translate": i1.TranslatePipe } });
1051
1710
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: ChannelHeaderComponent, decorators: [{
1052
1711
  type: Component,
1053
1712
  args: [{
@@ -1123,7 +1782,7 @@ class ChannelPreviewComponent {
1123
1782
  }
1124
1783
  }
1125
1784
  ChannelPreviewComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: ChannelPreviewComponent, deps: [{ token: ChannelService }], target: i0.ɵɵFactoryTarget.Component });
1126
- ChannelPreviewComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.5", type: ChannelPreviewComponent, selector: "stream-channel-preview", inputs: { channel: "channel" }, ngImport: i0, template: "<button\n class=\"str-chat__channel-preview-messenger\"\n [class.str-chat__channel-preview-messenger--active]=\"isActive\"\n [class.str-chat__channel-preview-messenger--unread]=\"isUnread\"\n (click)=\"setAsActiveChannel()\"\n data-testid=\"channel-preview-container\"\n>\n <div class=\"str-chat__channel-preview-messenger--left\">\n <stream-avatar\n imageUrl=\"{{ avatarImage }}\"\n name=\"{{ avatarName }}\"\n [size]=\"40\"\n ></stream-avatar>\n </div>\n <div class=\"str-chat__channel-preview-messenger--right\">\n <div class=\"str-chat__channel-preview-messenger--name\">\n <span data-testid=\"channel-preview-title\">{{ title }}</span>\n </div>\n <div\n data-testid=\"latest-message\"\n class=\"str-chat__channel-preview-messenger--last-message\"\n >\n {{ latestMessage | translate }}\n </div>\n </div>\n</button>\n", components: [{ type: AvatarComponent, selector: "stream-avatar", inputs: ["name", "imageUrl", "size"] }], pipes: { "translate": i4.TranslatePipe } });
1785
+ ChannelPreviewComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.5", type: ChannelPreviewComponent, selector: "stream-channel-preview", inputs: { channel: "channel" }, ngImport: i0, template: "<button\n class=\"str-chat__channel-preview-messenger\"\n [class.str-chat__channel-preview-messenger--active]=\"isActive\"\n [class.str-chat__channel-preview-messenger--unread]=\"isUnread\"\n (click)=\"setAsActiveChannel()\"\n data-testid=\"channel-preview-container\"\n>\n <div class=\"str-chat__channel-preview-messenger--left\">\n <stream-avatar\n imageUrl=\"{{ avatarImage }}\"\n name=\"{{ avatarName }}\"\n [size]=\"40\"\n ></stream-avatar>\n </div>\n <div class=\"str-chat__channel-preview-messenger--right\">\n <div class=\"str-chat__channel-preview-messenger--name\">\n <span data-testid=\"channel-preview-title\">{{ title }}</span>\n </div>\n <div\n data-testid=\"latest-message\"\n class=\"str-chat__channel-preview-messenger--last-message\"\n >\n {{ latestMessage | translate }}\n </div>\n </div>\n</button>\n", components: [{ type: AvatarComponent, selector: "stream-avatar", inputs: ["name", "imageUrl", "size"] }], pipes: { "translate": i1.TranslatePipe } });
1127
1786
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: ChannelPreviewComponent, decorators: [{
1128
1787
  type: Component,
1129
1788
  args: [{
@@ -1164,7 +1823,7 @@ class ChannelListComponent {
1164
1823
  }
1165
1824
  }
1166
1825
  ChannelListComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: ChannelListComponent, deps: [{ token: ChannelService }, { token: ChannelListToggleService }], target: i0.ɵɵFactoryTarget.Component });
1167
- ChannelListComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.5", type: ChannelListComponent, selector: "stream-channel-list", inputs: { customChannelPreviewTemplate: "customChannelPreviewTemplate" }, viewQueries: [{ propertyName: "container", first: true, predicate: ["container"], descendants: true }], ngImport: i0, template: "<div\n #container\n data-testid=\"channel-list-container\"\n class=\"str-chat str-chat-channel-list messaging\"\n [class.str-chat-channel-list--open]=\"(isOpen$ | async) === true\"\n>\n <div\n *ngIf=\"\n (isError$ | async) === false && (isInitializing$ | async) === false;\n else statusIndicator\n \"\n class=\"str-chat__channel-list-messenger\"\n >\n <div class=\"str-chat__channel-list-messenger__main\">\n <p\n data-testid=\"empty-channel-list-indicator\"\n *ngIf=\"!(channels$ | async)?.length\"\n >\n {{ \"streamChat.You have no channels currently\" | translate }}\n </p>\n <ng-container\n *ngFor=\"let channel of channels$ | async; trackBy: trackByChannelId\"\n >\n <ng-container\n *ngIf=\"customChannelPreviewTemplate; else defaultTemplate\"\n >\n <div (click)=\"channelSelected()\" (keyup.enter)=\"channelSelected()\">\n <ng-container\n *ngTemplateOutlet=\"\n customChannelPreviewTemplate;\n context: { channel: channel }\n \"\n ></ng-container>\n </div>\n </ng-container>\n <ng-template #defaultTemplate>\n <stream-channel-preview\n data-testclass=\"channel-preview\"\n [channel]=\"channel\"\n (click)=\"channelSelected()\"\n (keyup.enter)=\"channelSelected()\"\n ></stream-channel-preview>\n </ng-template>\n </ng-container>\n <div\n *ngIf=\"hasMoreChannels$ | async\"\n class=\"str-chat__load-more-button\"\n (click)=\"loadMoreChannels()\"\n (keyup.enter)=\"loadMoreChannels()\"\n data-testid=\"load-more\"\n >\n <button\n class=\"str-chat__load-more-button__button\"\n data-testid=\"load-more-button\"\n [disabled]=\"isLoadingMoreChannels\"\n >\n <span *ngIf=\"!isLoadingMoreChannels; else loadingIndicator\">{{\n \"Load more\" | translate\n }}</span>\n <ng-template #loadingIndicator\n ><stream-loading-indicator></stream-loading-indicator\n ></ng-template>\n </button>\n </div>\n </div>\n </div>\n</div>\n\n<ng-template #statusIndicator>\n <ng-container *ngIf=\"isError$ | async\">\n <ng-container *ngTemplateOutlet=\"chatDown\"></ng-container>\n </ng-container>\n <ng-container *ngIf=\"isInitializing$ | async\">\n <ng-container *ngTemplateOutlet=\"loadingChannels\"></ng-container>\n </ng-container>\n</ng-template>\n\n<ng-template #chatDown>\n <div data-testid=\"chatdown-container\" class=\"str-chat__down\">\n <ng-container *ngTemplateOutlet=\"loadingChannels\"></ng-container>\n <div class=\"str-chat__down-main\">\n <stream-icon icon=\"connection-error\"></stream-icon>\n <h1>{{ \"streamChat.Connection error\" | translate }}</h1>\n <h3>\n {{\n \"streamChat.Error connecting to chat, refresh the page to try again.\"\n | translate\n }}\n </h3>\n </div>\n </div>\n</ng-template>\n\n<ng-template #loadingChannels>\n <div data-testid=\"loading-indicator\" class=\"str-chat__loading-channels\">\n <ng-container *ngTemplateOutlet=\"loadingChannel\"></ng-container>\n <ng-container *ngTemplateOutlet=\"loadingChannel\"></ng-container>\n <ng-container *ngTemplateOutlet=\"loadingChannel\"></ng-container>\n </div>\n</ng-template>\n\n<ng-template #loadingChannel>\n <div class=\"str-chat__loading-channels-item\">\n <div class=\"str-chat__loading-channels-avatar\"></div>\n <div class=\"str-chat__loading-channels-meta\">\n <div class=\"str-chat__loading-channels-username\"></div>\n <div class=\"str-chat__loading-channels-status\"></div>\n </div>\n </div>\n</ng-template>\n", components: [{ type: ChannelPreviewComponent, selector: "stream-channel-preview", inputs: ["channel"] }, { type: LoadingIndicatorComponent, selector: "stream-loading-indicator", inputs: ["size", "color"] }, { type: IconComponent, selector: "stream-icon", inputs: ["icon", "size"] }], directives: [{ type: i5.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i5.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i5.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet"] }], pipes: { "async": i5.AsyncPipe, "translate": i4.TranslatePipe } });
1826
+ ChannelListComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.5", type: ChannelListComponent, selector: "stream-channel-list", inputs: { customChannelPreviewTemplate: "customChannelPreviewTemplate" }, viewQueries: [{ propertyName: "container", first: true, predicate: ["container"], descendants: true }], ngImport: i0, template: "<div\n #container\n data-testid=\"channel-list-container\"\n class=\"str-chat str-chat-channel-list messaging\"\n [class.str-chat-channel-list--open]=\"(isOpen$ | async) === true\"\n>\n <div\n *ngIf=\"\n (isError$ | async) === false && (isInitializing$ | async) === false;\n else statusIndicator\n \"\n class=\"str-chat__channel-list-messenger\"\n >\n <div class=\"str-chat__channel-list-messenger__main\">\n <p\n data-testid=\"empty-channel-list-indicator\"\n *ngIf=\"!(channels$ | async)?.length\"\n >\n {{ \"streamChat.You have no channels currently\" | translate }}\n </p>\n <ng-container\n *ngFor=\"let channel of channels$ | async; trackBy: trackByChannelId\"\n >\n <ng-container\n *ngIf=\"customChannelPreviewTemplate; else defaultTemplate\"\n >\n <div (click)=\"channelSelected()\" (keyup.enter)=\"channelSelected()\">\n <ng-container\n *ngTemplateOutlet=\"\n customChannelPreviewTemplate;\n context: { channel: channel }\n \"\n ></ng-container>\n </div>\n </ng-container>\n <ng-template #defaultTemplate>\n <stream-channel-preview\n data-testclass=\"channel-preview\"\n [channel]=\"channel\"\n (click)=\"channelSelected()\"\n (keyup.enter)=\"channelSelected()\"\n ></stream-channel-preview>\n </ng-template>\n </ng-container>\n <div\n *ngIf=\"hasMoreChannels$ | async\"\n class=\"str-chat__load-more-button\"\n (click)=\"loadMoreChannels()\"\n (keyup.enter)=\"loadMoreChannels()\"\n data-testid=\"load-more\"\n >\n <button\n class=\"str-chat__load-more-button__button\"\n data-testid=\"load-more-button\"\n [disabled]=\"isLoadingMoreChannels\"\n >\n <span *ngIf=\"!isLoadingMoreChannels; else loadingIndicator\">{{\n \"Load more\" | translate\n }}</span>\n <ng-template #loadingIndicator\n ><stream-loading-indicator></stream-loading-indicator\n ></ng-template>\n </button>\n </div>\n </div>\n </div>\n</div>\n\n<ng-template #statusIndicator>\n <ng-container *ngIf=\"isError$ | async\">\n <ng-container *ngTemplateOutlet=\"chatDown\"></ng-container>\n </ng-container>\n <ng-container *ngIf=\"isInitializing$ | async\">\n <ng-container *ngTemplateOutlet=\"loadingChannels\"></ng-container>\n </ng-container>\n</ng-template>\n\n<ng-template #chatDown>\n <div data-testid=\"chatdown-container\" class=\"str-chat__down\">\n <ng-container *ngTemplateOutlet=\"loadingChannels\"></ng-container>\n <div class=\"str-chat__down-main\">\n <stream-icon icon=\"connection-error\"></stream-icon>\n <h1>{{ \"streamChat.Connection error\" | translate }}</h1>\n <h3>\n {{\n \"streamChat.Error connecting to chat, refresh the page to try again.\"\n | translate\n }}\n </h3>\n </div>\n </div>\n</ng-template>\n\n<ng-template #loadingChannels>\n <div data-testid=\"loading-indicator\" class=\"str-chat__loading-channels\">\n <ng-container *ngTemplateOutlet=\"loadingChannel\"></ng-container>\n <ng-container *ngTemplateOutlet=\"loadingChannel\"></ng-container>\n <ng-container *ngTemplateOutlet=\"loadingChannel\"></ng-container>\n </div>\n</ng-template>\n\n<ng-template #loadingChannel>\n <div class=\"str-chat__loading-channels-item\">\n <div class=\"str-chat__loading-channels-avatar\"></div>\n <div class=\"str-chat__loading-channels-meta\">\n <div class=\"str-chat__loading-channels-username\"></div>\n <div class=\"str-chat__loading-channels-status\"></div>\n </div>\n </div>\n</ng-template>\n", components: [{ type: ChannelPreviewComponent, selector: "stream-channel-preview", inputs: ["channel"] }, { type: LoadingIndicatorComponent, selector: "stream-loading-indicator", inputs: ["size", "color"] }, { type: IconComponent, selector: "stream-icon", inputs: ["icon", "size"] }], directives: [{ type: i5.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i5.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i5.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet"] }], pipes: { "async": i5.AsyncPipe, "translate": i1.TranslatePipe } });
1168
1827
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: ChannelListComponent, decorators: [{
1169
1828
  type: Component,
1170
1829
  args: [{
@@ -1374,9 +2033,7 @@ class AttachmentListComponent {
1374
2033
  return index;
1375
2034
  }
1376
2035
  isImage(attachment) {
1377
- return (attachment.type === 'image' &&
1378
- !attachment.title_link &&
1379
- !attachment.og_scrape_url);
2036
+ return isImageAttachment(attachment);
1380
2037
  }
1381
2038
  isFile(attachment) {
1382
2039
  return attachment.type === 'file';
@@ -1417,6 +2074,27 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImpor
1417
2074
  type: Input
1418
2075
  }] } });
1419
2076
 
2077
+ class HighlightMentionsPipe {
2078
+ transform(value, mentionedUsers) {
2079
+ if (!value || !mentionedUsers) {
2080
+ return value || '';
2081
+ }
2082
+ let result = value;
2083
+ mentionedUsers.forEach((u) => {
2084
+ result = result.replace(new RegExp(`@${u.name || u.id}`, 'g'), `<b>@${u.name || u.id}</b>`);
2085
+ });
2086
+ return result;
2087
+ }
2088
+ }
2089
+ HighlightMentionsPipe.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: HighlightMentionsPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
2090
+ HighlightMentionsPipe.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: HighlightMentionsPipe, name: "highlightMentions" });
2091
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: HighlightMentionsPipe, decorators: [{
2092
+ type: Pipe,
2093
+ args: [{
2094
+ name: 'highlightMentions',
2095
+ }]
2096
+ }] });
2097
+
1420
2098
  class MessageComponent {
1421
2099
  constructor(chatClientService, channelService) {
1422
2100
  this.chatClientService = chatClientService;
@@ -1501,7 +2179,7 @@ class MessageComponent {
1501
2179
  }
1502
2180
  }
1503
2181
  MessageComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: MessageComponent, deps: [{ token: ChatClientService }, { token: ChannelService }], target: i0.ɵɵFactoryTarget.Component });
1504
- MessageComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.5", type: MessageComponent, selector: "stream-message", inputs: { message: "message", enabledMessageActions: "enabledMessageActions", areReactionsEnabled: "areReactionsEnabled", canReactToMessage: "canReactToMessage", isLastSentMessage: "isLastSentMessage" }, viewQueries: [{ propertyName: "container", first: true, predicate: ["container"], descendants: true }], ngImport: i0, template: "<div\n #container\n class=\"str-chat__message-simple str-chat__message str-chat__message--{{\n message?.type\n }} str-chat__message--{{ message?.status }} {{\n message?.text ? 'str-chat__message--has-text' : 'has-no-text'\n }}\"\n [class.str-chat__message--me]=\"isSentByCurrentUser\"\n [class.str-chat__message-simple--me]=\"isSentByCurrentUser\"\n [class.mobile-press]=\"isPressedOnMobile\"\n [class.str-chat__message--has-attachment]=\"hasAttachment\"\n [class.str-chat__message--with-reactions]=\"\n areReactionsEnabled && hasReactions\n \"\n data-testid=\"message-container\"\n>\n <ng-container *ngIf=\"!message?.deleted_at; else deletedMessage\">\n <ng-container *ngIf=\"message?.type !== 'system'; else systemMessage\">\n <ng-container\n *ngIf=\"\n isSentByCurrentUser &&\n ((isLastSentMessage && message?.status === 'received') ||\n message?.status === 'sending')\n \"\n >\n <ng-container *ngIf=\"message?.status === 'sending'; else sentStatus\">\n <ng-container *ngTemplateOutlet=\"sendingStatus\"></ng-container>\n </ng-container>\n <ng-template #sentStatus>\n <ng-container *ngIf=\"isMessageDeliveredAndRead; else deliveredStatus\">\n <ng-container *ngTemplateOutlet=\"readStatus\"></ng-container>\n </ng-container>\n </ng-template>\n </ng-container>\n <stream-avatar\n data-testid=\"avatar\"\n class=\"str-chat-angular__avatar-host\"\n [imageUrl]=\"message?.user?.image\"\n [name]=\"message?.user?.name || message?.user?.id\"\n ></stream-avatar>\n <div class=\"str-chat__message-inner\">\n <div\n class=\"str-chat__message-simple__actions\"\n data-testid=\"message-options\"\n *ngIf=\"areOptionsVisible\"\n >\n <div\n class=\"\n str-chat__message-simple__actions__action\n str-chat__message-simple__actions__action--options\n \"\n >\n <stream-message-actions-box\n [isOpen]=\"isActionBoxOpen\"\n [isMine]=\"isSentByCurrentUser\"\n [enabledActions]=\"enabledMessageActions\"\n [message]=\"message\"\n (displayedActionsCount)=\"visibleMessageActionsCount = $event\"\n ></stream-message-actions-box>\n <stream-icon\n *ngIf=\"visibleMessageActionsCount > 0\"\n data-testid=\"action-icon\"\n icon=\"action-icon\"\n (keyup.enter)=\"isActionBoxOpen = !isActionBoxOpen\"\n (click)=\"isActionBoxOpen = !isActionBoxOpen\"\n ></stream-icon>\n </div>\n <div\n *ngIf=\"areReactionsEnabled && canReactToMessage\"\n class=\"\n str-chat__message-simple__actions__action\n str-chat__message-simple__actions__action--reactions\n \"\n data-testid=\"reaction-icon\"\n (click)=\"isReactionSelectorOpen = !isReactionSelectorOpen\"\n (keyup.enter)=\"isReactionSelectorOpen = !isReactionSelectorOpen\"\n >\n <stream-icon icon=\"reaction-icon\"></stream-icon>\n </div>\n </div>\n <stream-message-reactions\n *ngIf=\"areReactionsEnabled\"\n [messageReactionCounts]=\"message?.reaction_counts || {}\"\n [latestReactions]=\"message?.latest_reactions || []\"\n [(isSelectorOpen)]=\"isReactionSelectorOpen\"\n [messageId]=\"message?.id\"\n [ownReactions]=\"message?.own_reactions || []\"\n ></stream-message-reactions>\n <stream-attachment-list\n *ngIf=\"hasAttachment\"\n [attachments]=\"message!.attachments!\"\n ></stream-attachment-list>\n <div class=\"str-chat__message-text\" *ngIf=\"message?.text\">\n <div\n data-testid=\"inner-message\"\n class=\"\n str-chat__message-text-inner str-chat__message-simple-text-inner\n \"\n [class.str-chat__message-light-text-inner--has-attachment]=\"\n hasAttachment\n \"\n (click)=\"\n message?.status === 'failed' && message?.errorStatusCode !== 403\n ? resendMessage()\n : undefined\n \"\n (keyup.enter)=\"\n message?.status === 'failed' && message?.errorStatusCode !== 403\n ? resendMessage()\n : undefined\n \"\n >\n <div\n data-testid=\"client-error-message\"\n *ngIf=\"message?.type === 'error'\"\n class=\"str-chat__simple-message--error-message\"\n >\n {{ \"streamChat.Error \u00B7 Unsent\" | translate }}\n </div>\n <div\n data-testid=\"error-message\"\n *ngIf=\"message?.status === 'failed'\"\n class=\"str-chat__simple-message--error-message\"\n >\n {{\n (message?.errorStatusCode === 403\n ? \"streamChat.Message Failed \u00B7 Unauthorized\"\n : \"streamChat.Message Failed \u00B7 Click to try again\"\n ) | translate\n }}\n </div>\n <div\n (click)=\"textClicked()\"\n (keyup.enter)=\"textClicked()\"\n data-testid=\"text\"\n [innerHTML]=\"message?.html || message?.text\"\n ></div>\n </div>\n </div>\n <div class=\"str-chat__message-data str-chat__message-simple-data\">\n <span\n data-testid=\"sender\"\n *ngIf=\"!isSentByCurrentUser\"\n class=\"str-chat__message-simple-name\"\n >\n {{ message?.user?.name ? message?.user?.name : message?.user?.id }}\n </span>\n <span data-testid=\"date\" class=\"str-chat__message-simple-timestamp\">\n {{ parsedDate }}\n </span>\n </div>\n </div>\n </ng-container>\n </ng-container>\n</div>\n\n<ng-template #sendingStatus>\n <span class=\"str-chat__message-simple-status\" data-testid=\"sending-indicator\">\n <div class=\"str-chat__tooltip\">\n {{ \"streamChat.Sending...\" | translate }}\n </div>\n <stream-loading-indicator\n data-testid=\"loading-indicator\"\n ></stream-loading-indicator>\n </span>\n</ng-template>\n<ng-template #readStatus>\n <span class=\"str-chat__message-simple-status\" data-testid=\"read-indicator\">\n <div class=\"str-chat__tooltip\" data-testid=\"read-by-tooltip\">\n {{ readByText }}\n </div>\n <stream-avatar\n class=\"str-chat-angular__avatar-host\"\n data-test-id=\"last-read-user-avatar\"\n [size]=\"15\"\n [imageUrl]=\"lastReadUser?.image\"\n [name]=\"lastReadUser?.name || lastReadUser?.id\"\n ></stream-avatar>\n <span\n data-test-id=\"read-by-length\"\n *ngIf=\"isReadByMultipleUsers\"\n class=\"str-chat__message-simple-status-number\"\n >\n {{ (message?.readBy)!.length }}\n </span>\n </span>\n</ng-template>\n<ng-template #deliveredStatus>\n <span\n class=\"str-chat__message-simple-status\"\n data-testid=\"delivered-indicator\"\n >\n <div class=\"str-chat__tooltip\">\n {{ \"streamChat.Delivered\" | translate }}\n </div>\n <stream-icon\n data-testid=\"delivered-icon\"\n icon=\"delivered-icon\"\n ></stream-icon>\n </span>\n</ng-template>\n\n<ng-template #deletedMessage>\n <div data-testid=\"message-deleted-component\">\n <div class=\"str-chat__message--deleted-inner\" translate>\n streamChat.This message was deleted...\n </div>\n </div>\n</ng-template>\n\n<ng-template #systemMessage>\n <div data-testid=\"system-message\" class=\"str-chat__message--system\">\n <div class=\"str-chat__message--system__text\">\n <div class=\"str-chat__message--system__line\"></div>\n <p>{{ message?.text }}</p>\n <div class=\"str-chat__message--system__line\"></div>\n </div>\n <div class=\"str-chat__message--system__date\">\n {{ parsedDate }}\n </div>\n </div>\n</ng-template>\n", components: [{ type: AvatarComponent, selector: "stream-avatar", inputs: ["name", "imageUrl", "size"] }, { type: MessageActionsBoxComponent, selector: "stream-message-actions-box", inputs: ["isOpen", "isMine", "message", "enabledActions"], outputs: ["displayedActionsCount"] }, { type: IconComponent, selector: "stream-icon", inputs: ["icon", "size"] }, { type: MessageReactionsComponent, selector: "stream-message-reactions", inputs: ["messageId", "messageReactionCounts", "isSelectorOpen", "latestReactions", "ownReactions"], outputs: ["isSelectorOpenChange"] }, { type: AttachmentListComponent, selector: "stream-attachment-list", inputs: ["attachments"] }, { type: LoadingIndicatorComponent, selector: "stream-loading-indicator", inputs: ["size", "color"] }], directives: [{ type: i5.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i5.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet"] }, { type: i4.TranslateDirective, selector: "[translate],[ngx-translate]", inputs: ["translate", "translateParams"] }], pipes: { "translate": i4.TranslatePipe } });
2182
+ MessageComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.5", type: MessageComponent, selector: "stream-message", inputs: { message: "message", enabledMessageActions: "enabledMessageActions", areReactionsEnabled: "areReactionsEnabled", canReactToMessage: "canReactToMessage", isLastSentMessage: "isLastSentMessage" }, viewQueries: [{ propertyName: "container", first: true, predicate: ["container"], descendants: true }], ngImport: i0, template: "<div\n #container\n class=\"str-chat__message-simple str-chat__message str-chat__message--{{\n message?.type\n }} str-chat__message--{{ message?.status }} {{\n message?.text ? 'str-chat__message--has-text' : 'has-no-text'\n }}\"\n [class.str-chat__message--me]=\"isSentByCurrentUser\"\n [class.str-chat__message-simple--me]=\"isSentByCurrentUser\"\n [class.mobile-press]=\"isPressedOnMobile\"\n [class.str-chat__message--has-attachment]=\"hasAttachment\"\n [class.str-chat__message--with-reactions]=\"\n areReactionsEnabled && hasReactions\n \"\n data-testid=\"message-container\"\n>\n <ng-container *ngIf=\"!message?.deleted_at; else deletedMessage\">\n <ng-container *ngIf=\"message?.type !== 'system'; else systemMessage\">\n <ng-container\n *ngIf=\"\n isSentByCurrentUser &&\n ((isLastSentMessage && message?.status === 'received') ||\n message?.status === 'sending')\n \"\n >\n <ng-container *ngIf=\"message?.status === 'sending'; else sentStatus\">\n <ng-container *ngTemplateOutlet=\"sendingStatus\"></ng-container>\n </ng-container>\n <ng-template #sentStatus>\n <ng-container *ngIf=\"isMessageDeliveredAndRead; else deliveredStatus\">\n <ng-container *ngTemplateOutlet=\"readStatus\"></ng-container>\n </ng-container>\n </ng-template>\n </ng-container>\n <stream-avatar\n data-testid=\"avatar\"\n class=\"str-chat-angular__avatar-host\"\n [imageUrl]=\"message?.user?.image\"\n [name]=\"message?.user?.name || message?.user?.id\"\n ></stream-avatar>\n <div class=\"str-chat__message-inner\">\n <div\n class=\"str-chat__message-simple__actions\"\n data-testid=\"message-options\"\n *ngIf=\"areOptionsVisible\"\n >\n <div\n data-testid=\"message-actions-container\"\n class=\"\n str-chat__message-simple__actions__action\n str-chat__message-simple__actions__action--options\n \"\n [class.str-chat-angular__message-simple__actions__action--options--editing]=\"\n isEditing\n \"\n >\n <stream-message-actions-box\n [isOpen]=\"isActionBoxOpen\"\n [isMine]=\"isSentByCurrentUser\"\n [enabledActions]=\"enabledMessageActions\"\n [message]=\"message\"\n (displayedActionsCount)=\"visibleMessageActionsCount = $event\"\n (isEditing)=\"isEditing = $event; isActionBoxOpen = !isEditing\"\n ></stream-message-actions-box>\n <stream-icon\n *ngIf=\"visibleMessageActionsCount > 0\"\n data-testid=\"action-icon\"\n icon=\"action-icon\"\n (keyup.enter)=\"isActionBoxOpen = !isActionBoxOpen\"\n (click)=\"isActionBoxOpen = !isActionBoxOpen\"\n ></stream-icon>\n </div>\n <div\n *ngIf=\"areReactionsEnabled && canReactToMessage\"\n class=\"\n str-chat__message-simple__actions__action\n str-chat__message-simple__actions__action--reactions\n \"\n data-testid=\"reaction-icon\"\n (click)=\"isReactionSelectorOpen = !isReactionSelectorOpen\"\n (keyup.enter)=\"isReactionSelectorOpen = !isReactionSelectorOpen\"\n >\n <stream-icon icon=\"reaction-icon\"></stream-icon>\n </div>\n </div>\n <stream-message-reactions\n *ngIf=\"areReactionsEnabled\"\n [messageReactionCounts]=\"message?.reaction_counts || {}\"\n [latestReactions]=\"message?.latest_reactions || []\"\n [(isSelectorOpen)]=\"isReactionSelectorOpen\"\n [messageId]=\"message?.id\"\n [ownReactions]=\"message?.own_reactions || []\"\n ></stream-message-reactions>\n <stream-attachment-list\n *ngIf=\"hasAttachment\"\n [attachments]=\"message!.attachments!\"\n ></stream-attachment-list>\n <div class=\"str-chat__message-text\" *ngIf=\"message?.text\">\n <div\n data-testid=\"inner-message\"\n class=\"\n str-chat__message-text-inner str-chat__message-simple-text-inner\n \"\n [class.str-chat__message-light-text-inner--has-attachment]=\"\n hasAttachment\n \"\n (click)=\"\n message?.status === 'failed' && message?.errorStatusCode !== 403\n ? resendMessage()\n : undefined\n \"\n (keyup.enter)=\"\n message?.status === 'failed' && message?.errorStatusCode !== 403\n ? resendMessage()\n : undefined\n \"\n >\n <div\n data-testid=\"client-error-message\"\n *ngIf=\"message?.type === 'error'\"\n class=\"str-chat__simple-message--error-message\"\n >\n {{ \"streamChat.Error \u00B7 Unsent\" | translate }}\n </div>\n <div\n data-testid=\"error-message\"\n *ngIf=\"message?.status === 'failed'\"\n class=\"str-chat__simple-message--error-message\"\n >\n {{\n (message?.errorStatusCode === 403\n ? \"streamChat.Message Failed \u00B7 Unauthorized\"\n : \"streamChat.Message Failed \u00B7 Click to try again\"\n ) | translate\n }}\n </div>\n <div\n (click)=\"textClicked()\"\n (keyup.enter)=\"textClicked()\"\n data-testid=\"text\"\n [innerHTML]=\"\n message?.html || message?.text\n | highlightMentions: message?.mentioned_users\n \"\n ></div>\n </div>\n </div>\n <div class=\"str-chat__message-data str-chat__message-simple-data\">\n <span\n data-testid=\"sender\"\n *ngIf=\"!isSentByCurrentUser\"\n class=\"str-chat__message-simple-name\"\n >\n {{ message?.user?.name ? message?.user?.name : message?.user?.id }}\n </span>\n <span data-testid=\"date\" class=\"str-chat__message-simple-timestamp\">\n {{ parsedDate }}\n </span>\n </div>\n </div>\n </ng-container>\n </ng-container>\n</div>\n\n<ng-template #sendingStatus>\n <span class=\"str-chat__message-simple-status\" data-testid=\"sending-indicator\">\n <div class=\"str-chat__tooltip\">\n {{ \"streamChat.Sending...\" | translate }}\n </div>\n <stream-loading-indicator\n data-testid=\"loading-indicator\"\n ></stream-loading-indicator>\n </span>\n</ng-template>\n<ng-template #readStatus>\n <span class=\"str-chat__message-simple-status\" data-testid=\"read-indicator\">\n <div class=\"str-chat__tooltip\" data-testid=\"read-by-tooltip\">\n {{ readByText }}\n </div>\n <stream-avatar\n class=\"str-chat-angular__avatar-host\"\n data-test-id=\"last-read-user-avatar\"\n [size]=\"15\"\n [imageUrl]=\"lastReadUser?.image\"\n [name]=\"lastReadUser?.name || lastReadUser?.id\"\n ></stream-avatar>\n <span\n data-test-id=\"read-by-length\"\n *ngIf=\"isReadByMultipleUsers\"\n class=\"str-chat__message-simple-status-number\"\n >\n {{ (message?.readBy)!.length }}\n </span>\n </span>\n</ng-template>\n<ng-template #deliveredStatus>\n <span\n class=\"str-chat__message-simple-status\"\n data-testid=\"delivered-indicator\"\n >\n <div class=\"str-chat__tooltip\">\n {{ \"streamChat.Delivered\" | translate }}\n </div>\n <stream-icon\n data-testid=\"delivered-icon\"\n icon=\"delivered-icon\"\n ></stream-icon>\n </span>\n</ng-template>\n\n<ng-template #deletedMessage>\n <div data-testid=\"message-deleted-component\">\n <div class=\"str-chat__message--deleted-inner\" translate>\n streamChat.This message was deleted...\n </div>\n </div>\n</ng-template>\n\n<ng-template #systemMessage>\n <div data-testid=\"system-message\" class=\"str-chat__message--system\">\n <div class=\"str-chat__message--system__text\">\n <div class=\"str-chat__message--system__line\"></div>\n <p>{{ message?.text }}</p>\n <div class=\"str-chat__message--system__line\"></div>\n </div>\n <div class=\"str-chat__message--system__date\">\n {{ parsedDate }}\n </div>\n </div>\n</ng-template>\n", components: [{ type: AvatarComponent, selector: "stream-avatar", inputs: ["name", "imageUrl", "size"] }, { type: MessageActionsBoxComponent, selector: "stream-message-actions-box", inputs: ["isOpen", "isMine", "message", "enabledActions"], outputs: ["displayedActionsCount", "isEditing"] }, { type: IconComponent, selector: "stream-icon", inputs: ["icon", "size"] }, { type: MessageReactionsComponent, selector: "stream-message-reactions", inputs: ["messageId", "messageReactionCounts", "isSelectorOpen", "latestReactions", "ownReactions"], outputs: ["isSelectorOpenChange"] }, { type: AttachmentListComponent, selector: "stream-attachment-list", inputs: ["attachments"] }, { type: LoadingIndicatorComponent, selector: "stream-loading-indicator", inputs: ["size", "color"] }], directives: [{ type: i5.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i5.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet"] }, { type: i1.TranslateDirective, selector: "[translate],[ngx-translate]", inputs: ["translate", "translateParams"] }], pipes: { "translate": i1.TranslatePipe, "highlightMentions": HighlightMentionsPipe } });
1505
2183
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: MessageComponent, decorators: [{
1506
2184
  type: Component,
1507
2185
  args: [{
@@ -1524,195 +2202,177 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImpor
1524
2202
  args: ['container']
1525
2203
  }] } });
1526
2204
 
1527
- class MessageInputComponent {
1528
- constructor(channelService, notificationService) {
2205
+ class TextareaComponent {
2206
+ constructor() {
2207
+ this.class = 'str-chat__textarea';
2208
+ this.value = '';
2209
+ this.valueChange = new EventEmitter();
2210
+ this.send = new EventEmitter();
2211
+ }
2212
+ // eslint-disable-next-line @angular-eslint/no-empty-lifecycle-method
2213
+ ngOnChanges() { }
2214
+ inputChanged() {
2215
+ this.valueChange.emit(this.messageInput.nativeElement.value);
2216
+ }
2217
+ sent(event) {
2218
+ event.preventDefault();
2219
+ this.send.next();
2220
+ }
2221
+ }
2222
+ TextareaComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: TextareaComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2223
+ TextareaComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.5", type: TextareaComponent, selector: "stream-textarea", inputs: { value: "value" }, outputs: { valueChange: "valueChange", send: "send" }, host: { properties: { "class": "this.class" } }, viewQueries: [{ propertyName: "messageInput", first: true, predicate: ["input"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<textarea\n [value]=\"value || ''\"\n autofocus\n data-testid=\"textarea\"\n #input\n placeholder=\"{{ 'streamChat.Type your message' | translate }}\"\n class=\"rta__textarea str-chat__textarea__textarea\"\n rows=\"1\"\n (input)=\"inputChanged()\"\n (keydown.enter)=\"sent($event)\"\n></textarea>\n", pipes: { "translate": i1.TranslatePipe } });
2224
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: TextareaComponent, decorators: [{
2225
+ type: Component,
2226
+ args: [{
2227
+ selector: 'stream-textarea',
2228
+ templateUrl: './textarea.component.html',
2229
+ styles: [],
2230
+ }]
2231
+ }], ctorParameters: function () { return []; }, propDecorators: { class: [{
2232
+ type: HostBinding
2233
+ }], value: [{
2234
+ type: Input
2235
+ }], valueChange: [{
2236
+ type: Output
2237
+ }], send: [{
2238
+ type: Output
2239
+ }], messageInput: [{
2240
+ type: ViewChild,
2241
+ args: ['input']
2242
+ }] } });
2243
+
2244
+ class AutocompleteTextareaComponent {
2245
+ constructor(channelService, chatClientService) {
1529
2246
  this.channelService = channelService;
1530
- this.notificationService = notificationService;
1531
- this.isFileUploadEnabled = true;
1532
- this.isMultipleFileUploadEnabled = true;
1533
- this.attachmentUploads = [];
1534
- this.attachmentUploadInProgressCounter = 0;
2247
+ this.chatClientService = chatClientService;
2248
+ this.class = 'str-chat__textarea';
2249
+ this.value = '';
2250
+ this.areMentionsEnabled = true;
2251
+ this.mentionScope = 'channel';
2252
+ this.valueChange = new EventEmitter();
2253
+ this.send = new EventEmitter();
2254
+ this.userMentions = new EventEmitter();
2255
+ this.labelKey = 'autocompleteLabel';
2256
+ this.triggerChar = '@';
2257
+ this.autocompleteConfig = {
2258
+ mentions: [],
2259
+ };
1535
2260
  this.subscriptions = [];
1536
- this.subscriptions.push(this.channelService.activeChannel$.subscribe((channel) => {
1537
- var _a;
1538
- if (this.messageInput) {
1539
- this.messageInput.nativeElement.value = '';
1540
- }
1541
- this.attachmentUploads = [];
1542
- const capabilities = (_a = channel === null || channel === void 0 ? void 0 : channel.data) === null || _a === void 0 ? void 0 : _a.own_capabilities;
1543
- if (capabilities) {
1544
- this.isFileUploadAuthorized =
1545
- capabilities.indexOf('upload-file') !== -1;
1546
- }
2261
+ this.mentionedUsers = [];
2262
+ this.userMentionConfig = {
2263
+ triggerChar: this.triggerChar,
2264
+ dropUp: true,
2265
+ labelKey: this.labelKey,
2266
+ mentionFilter: this.filter,
2267
+ mentionSelect: (item, triggerChar) => this.mentioned(item, triggerChar),
2268
+ };
2269
+ this.searchTerm$ = new BehaviorSubject('');
2270
+ this.searchTerm$
2271
+ .pipe(debounceTime(300), distinctUntilChanged())
2272
+ .subscribe((searchTerm) => void this.updateMentionOptions(searchTerm));
2273
+ this.subscriptions.push(this.channelService.activeChannel$.subscribe(() => {
2274
+ this.mentionedUsers = [];
2275
+ this.userMentions.next([...this.mentionedUsers]);
2276
+ void this.updateMentionOptions(this.searchTerm$.getValue());
1547
2277
  }));
1548
2278
  }
1549
- ngOnDestroy() {
1550
- this.subscriptions.forEach((s) => s.unsubscribe());
1551
- }
1552
- messageSent(event) {
1553
- return __awaiter(this, void 0, void 0, function* () {
1554
- event === null || event === void 0 ? void 0 : event.preventDefault();
1555
- if (this.attachmentUploadInProgressCounter > 0) {
1556
- if (!this.hideNotification) {
1557
- this.hideNotification =
1558
- this.notificationService.addPermanentNotification('streamChat.Wait until all attachments have uploaded');
1559
- }
1560
- return;
2279
+ ngOnChanges(changes) {
2280
+ if (changes.areMentionsEnabled) {
2281
+ if (this.areMentionsEnabled) {
2282
+ this.autocompleteConfig.mentions = [this.userMentionConfig];
2283
+ this.autocompleteConfig = Object.assign({}, this.autocompleteConfig);
1561
2284
  }
1562
- const text = this.messageInput.nativeElement.value;
1563
- const attachments = this.attachmentUploads
1564
- .filter((r) => r.state === 'success')
1565
- .map((r) => {
1566
- const attachment = {
1567
- type: r.type,
1568
- };
1569
- if (r.type === 'image') {
1570
- attachment.fallback = r.file.name;
1571
- attachment.image_url = r.url;
1572
- }
1573
- else {
1574
- attachment.asset_url = r.url;
1575
- attachment.title = r.file.name;
1576
- attachment.file_size = r.file.size;
1577
- }
1578
- return attachment;
1579
- });
1580
- this.messageInput.nativeElement.value = '';
1581
- yield this.channelService.sendMessage(text, attachments);
1582
- this.attachmentUploads = [];
1583
- });
2285
+ else {
2286
+ this.autocompleteConfig.mentions = [];
2287
+ this.autocompleteConfig = Object.assign({}, this.autocompleteConfig);
2288
+ }
2289
+ }
2290
+ if (changes.mentionScope) {
2291
+ void this.updateMentionOptions(this.searchTerm$.getValue());
2292
+ }
1584
2293
  }
1585
- get accept() {
1586
- var _a;
1587
- return this.acceptedFileTypes ? (_a = this.acceptedFileTypes) === null || _a === void 0 ? void 0 : _a.join(',') : '';
2294
+ filter(searchString, items) {
2295
+ return items.filter((item) => item.autocompleteLabel.toLowerCase().includes(searchString.toLowerCase()));
1588
2296
  }
1589
- filesSelected(fileList) {
1590
- return __awaiter(this, void 0, void 0, function* () {
1591
- if (!fileList) {
1592
- return;
1593
- }
1594
- const imageFiles = [];
1595
- const dataFiles = [];
1596
- Array.from(fileList).forEach((file) => {
1597
- if (file.type.startsWith('image/') && !file.type.endsWith('.photoshop')) {
1598
- // photoshop files begin with 'image/'
1599
- imageFiles.push(file);
1600
- }
1601
- else {
1602
- dataFiles.push(file);
1603
- }
1604
- });
1605
- imageFiles.forEach((f) => this.createPreview(f));
1606
- const newUploads = [
1607
- ...imageFiles.map((file) => ({
1608
- file,
1609
- state: 'uploading',
1610
- type: 'image',
1611
- })),
1612
- ...dataFiles.map((file) => ({
1613
- file,
1614
- state: 'uploading',
1615
- type: 'file',
1616
- })),
1617
- ];
1618
- this.attachmentUploads = [...this.attachmentUploads, ...newUploads];
1619
- this.clearFileInput();
1620
- yield this.uploadAttachments(newUploads);
1621
- });
2297
+ mentioned(item, triggerChar = '') {
2298
+ this.mentionedUsers.push((item.user ? item.user : item));
2299
+ this.userMentions.next([...this.mentionedUsers]);
2300
+ return triggerChar + item.autocompleteLabel;
1622
2301
  }
1623
- retryAttachmentUpload(file) {
1624
- return __awaiter(this, void 0, void 0, function* () {
1625
- const upload = this.attachmentUploads.find((u) => u.file === file);
1626
- if (!upload) {
1627
- return;
1628
- }
1629
- upload.state = 'uploading';
1630
- yield this.uploadAttachments([upload]);
1631
- });
2302
+ autcompleteSearchTermChanged(searchTerm) {
2303
+ this.searchTerm$.next(searchTerm);
1632
2304
  }
1633
- deleteAttachment(upload) {
1634
- return __awaiter(this, void 0, void 0, function* () {
1635
- if (upload.state === 'success') {
1636
- try {
1637
- yield this.channelService.deleteAttachment(upload);
1638
- this.attachmentUploads.splice(this.attachmentUploads.indexOf(upload), 1);
1639
- }
1640
- catch (error) {
1641
- // TODO error handling
1642
- }
1643
- }
1644
- else {
1645
- this.attachmentUploads.splice(this.attachmentUploads.indexOf(upload), 1);
1646
- }
1647
- });
2305
+ inputChanged() {
2306
+ this.valueChange.emit(this.messageInput.nativeElement.value);
1648
2307
  }
1649
- trackByFile(_, item) {
1650
- return item.file;
2308
+ inputLeft() {
2309
+ this.updateMentionedUsersFromText();
1651
2310
  }
1652
- createPreview(file) {
1653
- const reader = new FileReader();
1654
- reader.onload = (event) => {
1655
- var _a;
1656
- const upload = this.attachmentUploads.find((upload) => upload.file === file);
1657
- if (!upload) {
1658
- return;
1659
- }
1660
- upload.previewUri = ((_a = event.target) === null || _a === void 0 ? void 0 : _a.result) || undefined;
1661
- };
1662
- reader.readAsDataURL(file);
2311
+ sent(event) {
2312
+ event.preventDefault();
2313
+ this.updateMentionedUsersFromText();
2314
+ this.send.next();
1663
2315
  }
1664
- uploadAttachments(uploads) {
2316
+ updateMentionOptions(searchTerm) {
1665
2317
  return __awaiter(this, void 0, void 0, function* () {
1666
- this.attachmentUploadInProgressCounter++;
1667
- const result = yield this.channelService.uploadAttachments(uploads);
1668
- result.forEach((r) => {
1669
- const upload = this.attachmentUploads.find((upload) => upload.file === r.file);
1670
- if (!upload) {
1671
- if (r.url) {
1672
- void this.channelService.deleteAttachment(r);
1673
- }
1674
- return;
1675
- }
1676
- upload.state = r.state;
1677
- upload.url = r.url;
1678
- if (upload.state === 'error') {
1679
- this.notificationService.addTemporaryNotification(upload.type === 'image'
1680
- ? 'streamChat.Error uploading image'
1681
- : 'streamChat.Error uploading file');
1682
- }
1683
- });
1684
- this.attachmentUploadInProgressCounter--;
1685
- if (this.attachmentUploadInProgressCounter === 0 && this.hideNotification) {
1686
- this.hideNotification();
1687
- this.hideNotification = undefined;
2318
+ if (!this.areMentionsEnabled) {
2319
+ return;
1688
2320
  }
2321
+ const request = this.mentionScope === 'application'
2322
+ ? (s) => this.chatClientService.autocompleteUsers(s)
2323
+ : (s) => this.channelService.autocompleteMembers(s);
2324
+ const result = yield request(searchTerm || '');
2325
+ const items = this.filter(searchTerm || '', result.map((i) => {
2326
+ const user = (i.user ? i.user : i);
2327
+ return Object.assign(Object.assign({}, i), { autocompleteLabel: user.name || user.id, type: 'mention' });
2328
+ }));
2329
+ this.userMentionConfig.items = items;
2330
+ this.autocompleteConfig.mentions = [this.userMentionConfig];
2331
+ this.autocompleteConfig = Object.assign({}, this.autocompleteConfig);
1689
2332
  });
1690
2333
  }
1691
- clearFileInput() {
1692
- this.fileInput.nativeElement.value = '';
2334
+ updateMentionedUsersFromText() {
2335
+ const updatedMentionedUsers = [];
2336
+ this.mentionedUsers.forEach((u) => {
2337
+ const key = u.name || u.id;
2338
+ if (this.value.includes(`${this.triggerChar}${key}`)) {
2339
+ updatedMentionedUsers.push(u);
2340
+ }
2341
+ });
2342
+ if (updatedMentionedUsers.length !== this.mentionedUsers.length) {
2343
+ this.userMentions.next([...updatedMentionedUsers]);
2344
+ this.mentionedUsers = updatedMentionedUsers;
2345
+ }
1693
2346
  }
1694
2347
  }
1695
- MessageInputComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: MessageInputComponent, deps: [{ token: ChannelService }, { token: NotificationService }], target: i0.ɵɵFactoryTarget.Component });
1696
- MessageInputComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.5", type: MessageInputComponent, selector: "stream-message-input", inputs: { isFileUploadEnabled: "isFileUploadEnabled", acceptedFileTypes: "acceptedFileTypes", isMultipleFileUploadEnabled: "isMultipleFileUploadEnabled" }, viewQueries: [{ propertyName: "messageInput", first: true, predicate: ["input"], descendants: true }, { propertyName: "fileInput", first: true, predicate: ["fileInput"], descendants: true }], ngImport: i0, template: "<div class=\"str-chat__input-flat\">\n <div class=\"str-chat__input-flat-wrapper\">\n <div class=\"str-chat__input-flat--textarea-wrapper\">\n <div class=\"rfu-image-previewer\">\n <ng-container\n *ngFor=\"\n let attachmentUpload of attachmentUploads;\n trackBy: trackByFile\n \"\n >\n <div\n *ngIf=\"attachmentUpload.type === 'image'\"\n class=\"rfu-image-previewer__image\"\n [class.rfu-image-previewer__image--loaded]=\"\n attachmentUpload.state === 'success'\n \"\n data-testclass=\"attachment-image-preview\"\n >\n <div\n *ngIf=\"attachmentUpload.state === 'error'\"\n class=\"rfu-image-previewer__retry\"\n (click)=\"retryAttachmentUpload(attachmentUpload.file)\"\n (keyup.enter)=\"retryAttachmentUpload(attachmentUpload.file)\"\n data-testclass=\"upload-error\"\n >\n <stream-icon icon=\"retry\"></stream-icon>\n </div>\n <div class=\"rfu-thumbnail__wrapper\" style=\"width: 100; height: 100\">\n <div class=\"rfu-thumbnail__overlay\">\n <div\n class=\"rfu-icon-button\"\n data-testclass=\"delete-attachment\"\n role=\"button\"\n (click)=\"deleteAttachment(attachmentUpload)\"\n (keyup.enter)=\"deleteAttachment(attachmentUpload)\"\n >\n <stream-icon icon=\"close\"></stream-icon>\n </div>\n </div>\n <img\n *ngIf=\"attachmentUpload.url || attachmentUpload.previewUri\"\n src=\"{{\n attachmentUpload.url\n ? attachmentUpload.url\n : attachmentUpload.previewUri\n }}\"\n alt=\"attachmentUpload.file.name\"\n class=\"rfu-thumbnail__image\"\n data-testclass=\"attachment-image\"\n />\n </div>\n <stream-loading-indicator\n data-testclass=\"loading-indicator\"\n color=\"rgba(255,255,255,0.7)\"\n *ngIf=\"attachmentUpload.state === 'uploading'\"\n ></stream-loading-indicator>\n </div>\n <div\n class=\"rfu-file-previewer\"\n *ngIf=\"attachmentUpload.type === 'file'\"\n data-testclass=\"attachment-file-preview\"\n >\n <ol>\n <li\n class=\"rfu-file-previewer__file\"\n [class.rfu-file-previewer__file--uploading]=\"\n attachmentUpload.state === 'uploading'\n \"\n [class.rfu-file-previewer__file--failed]=\"\n attachmentUpload.state === 'error'\n \"\n >\n <stream-icon icon=\"file\"></stream-icon>\n\n <a\n data-testclass=\"file-download-link\"\n href=\"{{ attachmentUpload.url }}\"\n (click)=\"\n attachmentUpload.url ? null : $event.preventDefault()\n \"\n (keyup.enter)=\"\n attachmentUpload.url ? null : $event.preventDefault()\n \"\n download\n >\n {{ attachmentUpload.file.name }}\n <ng-container *ngIf=\"attachmentUpload.state === 'error'\">\n <div\n data-testclass=\"file-upload-retry\"\n class=\"rfu-file-previewer__failed\"\n (click)=\"retryAttachmentUpload(attachmentUpload.file)\"\n (keyup.enter)=\"\n retryAttachmentUpload(attachmentUpload.file)\n \"\n translate\n >\n streamChat.failed\n </div>\n <div\n class=\"rfu-file-previewer__retry\"\n (click)=\"retryAttachmentUpload(attachmentUpload.file)\"\n (keyup.enter)=\"\n retryAttachmentUpload(attachmentUpload.file)\n \"\n translate\n >\n streamChat.retry\n </div>\n </ng-container>\n </a>\n\n <span\n data-testclass=\"file-delete\"\n class=\"rfu-file-previewer__close-button\"\n (click)=\"deleteAttachment(attachmentUpload)\"\n (keyup.enter)=\"deleteAttachment(attachmentUpload)\"\n >\n \u2718\n </span>\n <div\n *ngIf=\"attachmentUpload.state === 'uploading'\"\n class=\"rfu-file-previewer__loading-indicator\"\n >\n <stream-loading-indicator></stream-loading-indicator>\n </div>\n </li>\n </ol>\n </div>\n </ng-container>\n </div>\n <div class=\"rta str-chat__textarea\">\n <textarea\n autofocus\n data-testid=\"textarea\"\n #input\n placeholder=\"{{ 'streamChat.Type your message' | translate }}\"\n class=\"rta__textarea str-chat__textarea__textarea\"\n rows=\"1\"\n (keydown.enter)=\"messageSent($event)\"\n ></textarea>\n </div>\n <div\n *ngIf=\"isFileUploadEnabled && isFileUploadAuthorized\"\n class=\"str-chat__fileupload-wrapper\"\n data-testid=\"file-upload-button\"\n >\n <div class=\"str-chat__tooltip\">\n {{ \"streamChat.Attach files\" | translate }}\n </div>\n <div class=\"rfu-file-upload-button\">\n <label>\n <input\n #fileInput\n type=\"file\"\n class=\"rfu-file-input\"\n data-testid=\"file-input\"\n [accept]=\"accept\"\n [multiple]=\"isMultipleFileUploadEnabled\"\n (change)=\"filesSelected(fileInput.files)\"\n />\n <span class=\"str-chat__input-flat-fileupload\">\n <stream-icon icon=\"file-upload\"></stream-icon>\n </span>\n </label>\n </div>\n </div>\n </div>\n <button\n data-testid=\"send-button\"\n class=\"str-chat__send-button\"\n (click)=\"messageSent()\"\n (keyup.enter)=\"messageSent()\"\n >\n <stream-icon icon=\"send\"></stream-icon>\n </button>\n </div>\n</div>\n", components: [{ type: IconComponent, selector: "stream-icon", inputs: ["icon", "size"] }, { type: LoadingIndicatorComponent, selector: "stream-loading-indicator", inputs: ["size", "color"] }], directives: [{ type: i5.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i5.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i4.TranslateDirective, selector: "[translate],[ngx-translate]", inputs: ["translate", "translateParams"] }], pipes: { "translate": i4.TranslatePipe } });
1697
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: MessageInputComponent, decorators: [{
2348
+ AutocompleteTextareaComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: AutocompleteTextareaComponent, deps: [{ token: ChannelService }, { token: ChatClientService }], target: i0.ɵɵFactoryTarget.Component });
2349
+ AutocompleteTextareaComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.5", type: AutocompleteTextareaComponent, selector: "stream-autocomplete-textarea", inputs: { value: "value", areMentionsEnabled: "areMentionsEnabled", mentionAutocompleteItemTemplate: "mentionAutocompleteItemTemplate", mentionScope: "mentionScope" }, outputs: { valueChange: "valueChange", send: "send", userMentions: "userMentions" }, host: { properties: { "class": "this.class" } }, viewQueries: [{ propertyName: "messageInput", first: true, predicate: ["input"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<textarea\n [value]=\"value || ''\"\n autofocus\n data-testid=\"textarea\"\n #input\n placeholder=\"{{ 'streamChat.Type your message' | translate }}\"\n class=\"rta__textarea str-chat__textarea__textarea\"\n rows=\"1\"\n (input)=\"inputChanged()\"\n (keydown.enter)=\"sent($event)\"\n [mentionConfig]=\"autocompleteConfig\"\n (searchTerm)=\"autcompleteSearchTermChanged($event)\"\n [mentionListTemplate]=\"autocompleteItem\"\n (blur)=\"inputLeft()\"\n></textarea>\n<ng-template #autocompleteItem let-item=\"item\">\n <div class=\"rta rta__item str-chat__emojisearch__item\" [ngSwitch]=\"item.type\">\n <div class=\"rta__entity\" *ngSwitchCase=\"'mention'\">\n <ng-container\n *ngTemplateOutlet=\"\n mentionAutocompleteItemTemplate || defaultMentionTemplate;\n context: { item: item }\n \"\n ></ng-container>\n </div>\n </div>\n</ng-template>\n\n<ng-template #defaultMentionTemplate let-item=\"item\">\n <div class=\"str-chat__user-item\">\n <stream-avatar\n data-testclass=\"avatar\"\n class=\"str-chat__avatar str-chat__avatar--circle\"\n style=\"height: 20px\"\n [size]=\"20\"\n [imageUrl]=\"item.image || item.user?.image\"\n [name]=\"item.autocompleteLabel\"\n ></stream-avatar>\n <span data-testclass=\"username\" class=\"str-chat__user-item--name\">{{\n item.autocompleteLabel\n }}</span>\n </div>\n</ng-template>\n", components: [{ type: AvatarComponent, selector: "stream-avatar", inputs: ["name", "imageUrl", "size"] }], directives: [{ type: i4.MentionDirective, selector: "[mention], [mentionConfig]", inputs: ["mentionConfig", "mention", "mentionListTemplate"], outputs: ["searchTerm", "itemSelected", "opened", "closed"] }, { type: i5.NgSwitch, selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { type: i5.NgSwitchCase, selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }, { type: i5.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet"] }], pipes: { "translate": i1.TranslatePipe } });
2350
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: AutocompleteTextareaComponent, decorators: [{
1698
2351
  type: Component,
1699
2352
  args: [{
1700
- selector: 'stream-message-input',
1701
- templateUrl: './message-input.component.html',
2353
+ selector: 'stream-autocomplete-textarea',
2354
+ templateUrl: './autocomplete-textarea.component.html',
1702
2355
  styles: [],
1703
2356
  }]
1704
- }], ctorParameters: function () { return [{ type: ChannelService }, { type: NotificationService }]; }, propDecorators: { isFileUploadEnabled: [{
2357
+ }], ctorParameters: function () { return [{ type: ChannelService }, { type: ChatClientService }]; }, propDecorators: { class: [{
2358
+ type: HostBinding
2359
+ }], value: [{
1705
2360
  type: Input
1706
- }], acceptedFileTypes: [{
2361
+ }], areMentionsEnabled: [{
1707
2362
  type: Input
1708
- }], isMultipleFileUploadEnabled: [{
2363
+ }], mentionAutocompleteItemTemplate: [{
2364
+ type: Input
2365
+ }], mentionScope: [{
1709
2366
  type: Input
2367
+ }], valueChange: [{
2368
+ type: Output
2369
+ }], send: [{
2370
+ type: Output
2371
+ }], userMentions: [{
2372
+ type: Output
1710
2373
  }], messageInput: [{
1711
2374
  type: ViewChild,
1712
2375
  args: ['input']
1713
- }], fileInput: [{
1714
- type: ViewChild,
1715
- args: ['fileInput']
1716
2376
  }] } });
1717
2377
 
1718
2378
  const getGroupStyles = (message, previousMessage, nextMessage, noGroupByUser = false) => {
@@ -1761,7 +2421,9 @@ class MessageListComponent {
1761
2421
  this.chatClientService = chatClientService;
1762
2422
  this.imageLoadService = imageLoadService;
1763
2423
  this.areReactionsEnabled = true;
1764
- this.enabledMessageActions = ['flag'];
2424
+ /* eslint-disable-next-line @angular-eslint/no-input-rename */
2425
+ this.enabledMessageActionsInput = ['flag', 'edit', 'edit-any', 'delete', 'delete-any'];
2426
+ this.enabledMessageActions = [];
1765
2427
  this.class = 'str-chat-angular__main-panel-inner str-chat-angular__message-list-host';
1766
2428
  this.unreadMessageCount = 0;
1767
2429
  this.groupStyles = [];
@@ -1784,6 +2446,20 @@ class MessageListComponent {
1784
2446
  if (capabilites.indexOf('flag-message') !== -1) {
1785
2447
  this.authorizedMessageActions.push('flag');
1786
2448
  }
2449
+ if (capabilites.indexOf('update-own-message') !== -1) {
2450
+ this.authorizedMessageActions.push('edit');
2451
+ }
2452
+ if (capabilites.indexOf('update-any-message') !== -1) {
2453
+ this.authorizedMessageActions.push('edit');
2454
+ this.authorizedMessageActions.push('edit-any');
2455
+ }
2456
+ if (capabilites.indexOf('delete-own-message') !== -1) {
2457
+ this.authorizedMessageActions.push('delete');
2458
+ }
2459
+ if (capabilites.indexOf('delete-any-message') !== -1) {
2460
+ this.authorizedMessageActions.push('delete');
2461
+ this.authorizedMessageActions.push('delete-any');
2462
+ }
1787
2463
  this.setEnabledActions();
1788
2464
  }
1789
2465
  });
@@ -1883,10 +2559,10 @@ class MessageListComponent {
1883
2559
  this.scrollContainer.nativeElement.scrollHeight - this.containerHeight;
1884
2560
  }
1885
2561
  setEnabledActions() {
2562
+ this.enabledMessageActions = [];
1886
2563
  if (!this.enabledMessageActionsInput) {
1887
2564
  return;
1888
2565
  }
1889
- this.enabledMessageActions = [];
1890
2566
  this.enabledMessageActionsInput.forEach((action) => {
1891
2567
  const isAuthorized = this.authorizedMessageActions.indexOf(action) !== -1;
1892
2568
  if (isAuthorized) {
@@ -1919,47 +2595,24 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImpor
1919
2595
  args: ['scrollContainer']
1920
2596
  }] } });
1921
2597
 
1922
- class NotificationComponent {
1923
- constructor() { }
1924
- }
1925
- NotificationComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: NotificationComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1926
- NotificationComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.5", type: NotificationComponent, selector: "stream-notification", inputs: { type: "type" }, ngImport: i0, template: "<div\n class=\"str-chat__custom-notification notification-{{ type }}\"\n data-testid=\"custom-notification\"\n>\n <ng-content></ng-content>\n</div>\n" });
1927
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: NotificationComponent, decorators: [{
1928
- type: Component,
1929
- args: [{
1930
- selector: 'stream-notification',
1931
- templateUrl: './notification.component.html',
1932
- styles: [],
1933
- }]
1934
- }], ctorParameters: function () { return []; }, propDecorators: { type: [{
1935
- type: Input
1936
- }] } });
1937
-
1938
- class NotificationListComponent {
1939
- constructor(notificationService) {
1940
- this.notificationService = notificationService;
1941
- this.notifications$ = this.notificationService.notifications$;
1942
- }
1943
- trackByItem(_, item) {
1944
- return item;
1945
- }
2598
+ class StreamAvatarModule {
1946
2599
  }
1947
- NotificationListComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: NotificationListComponent, deps: [{ token: NotificationService }], target: i0.ɵɵFactoryTarget.Component });
1948
- NotificationListComponentcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.5", type: NotificationListComponent, selector: "stream-notification-list", ngImport: i0, template: "<div class=\"str-chat__list-notifications\">\n <stream-notification\n *ngFor=\"let notification of notifications$ | async; trackBy: trackByItem\"\n [type]=\"notification.type\"\n ><div data-testclass=\"notification-content\" translate>\n {{ notification.text }}\n </div></stream-notification\n >\n</div>\n", components: [{ type: NotificationComponent, selector: "stream-notification", inputs: ["type"] }], directives: [{ type: i5.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i4.TranslateDirective, selector: "[translate],[ngx-translate]", inputs: ["translate", "translateParams"] }], pipes: { "async": i5.AsyncPipe } });
1949
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: NotificationListComponent, decorators: [{
1950
- type: Component,
2600
+ StreamAvatarModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: StreamAvatarModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
2601
+ StreamAvatarModulemod = i0.ɵɵngDeclareNgModule({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: StreamAvatarModule, declarations: [AvatarComponent], imports: [CommonModule, TranslateModule], exports: [AvatarComponent] });
2602
+ StreamAvatarModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: StreamAvatarModule, imports: [[CommonModule, TranslateModule]] });
2603
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: StreamAvatarModule, decorators: [{
2604
+ type: NgModule,
1951
2605
  args: [{
1952
- selector: 'stream-notification-list',
1953
- templateUrl: './notification-list.component.html',
1954
- styles: [],
2606
+ declarations: [AvatarComponent],
2607
+ imports: [CommonModule, TranslateModule],
2608
+ exports: [AvatarComponent],
1955
2609
  }]
1956
- }], ctorParameters: function () { return [{ type: NotificationService }]; } });
2610
+ }] });
1957
2611
 
1958
2612
  class StreamChatModule {
1959
2613
  }
1960
2614
  StreamChatModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: StreamChatModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
1961
- StreamChatModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: StreamChatModule, declarations: [AvatarComponent,
1962
- ChannelComponent,
2615
+ StreamChatModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: StreamChatModule, declarations: [ChannelComponent,
1963
2616
  ChannelHeaderComponent,
1964
2617
  ChannelListComponent,
1965
2618
  ChannelPreviewComponent,
@@ -1972,8 +2625,11 @@ StreamChatModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "12.0.0", versio
1972
2625
  AttachmentListComponent,
1973
2626
  MessageReactionsComponent,
1974
2627
  NotificationComponent,
1975
- NotificationListComponent], imports: [CommonModule, EmojiModule, TranslateModule], exports: [AvatarComponent,
1976
- ChannelComponent,
2628
+ NotificationListComponent,
2629
+ AttachmentPreviewListComponent,
2630
+ ModalComponent,
2631
+ TextareaDirective,
2632
+ HighlightMentionsPipe], imports: [CommonModule, EmojiModule, TranslateModule, StreamAvatarModule], exports: [ChannelComponent,
1977
2633
  ChannelHeaderComponent,
1978
2634
  ChannelListComponent,
1979
2635
  ChannelPreviewComponent,
@@ -1986,13 +2642,15 @@ StreamChatModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "12.0.0", versio
1986
2642
  AttachmentListComponent,
1987
2643
  MessageReactionsComponent,
1988
2644
  NotificationComponent,
1989
- NotificationListComponent] });
1990
- StreamChatModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: StreamChatModule, imports: [[CommonModule, EmojiModule, TranslateModule]] });
2645
+ NotificationListComponent,
2646
+ AttachmentPreviewListComponent,
2647
+ ModalComponent,
2648
+ HighlightMentionsPipe] });
2649
+ StreamChatModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: StreamChatModule, imports: [[CommonModule, EmojiModule, TranslateModule, StreamAvatarModule]] });
1991
2650
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: StreamChatModule, decorators: [{
1992
2651
  type: NgModule,
1993
2652
  args: [{
1994
2653
  declarations: [
1995
- AvatarComponent,
1996
2654
  ChannelComponent,
1997
2655
  ChannelHeaderComponent,
1998
2656
  ChannelListComponent,
@@ -2007,10 +2665,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImpor
2007
2665
  MessageReactionsComponent,
2008
2666
  NotificationComponent,
2009
2667
  NotificationListComponent,
2668
+ AttachmentPreviewListComponent,
2669
+ ModalComponent,
2670
+ TextareaDirective,
2671
+ HighlightMentionsPipe,
2010
2672
  ],
2011
- imports: [CommonModule, EmojiModule, TranslateModule],
2673
+ imports: [CommonModule, EmojiModule, TranslateModule, StreamAvatarModule],
2012
2674
  exports: [
2013
- AvatarComponent,
2014
2675
  ChannelComponent,
2015
2676
  ChannelHeaderComponent,
2016
2677
  ChannelListComponent,
@@ -2025,6 +2686,59 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImpor
2025
2686
  MessageReactionsComponent,
2026
2687
  NotificationComponent,
2027
2688
  NotificationListComponent,
2689
+ AttachmentPreviewListComponent,
2690
+ ModalComponent,
2691
+ HighlightMentionsPipe,
2692
+ ],
2693
+ }]
2694
+ }] });
2695
+
2696
+ class StreamAutocompleteTextareaModule {
2697
+ }
2698
+ StreamAutocompleteTextareaModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: StreamAutocompleteTextareaModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
2699
+ StreamAutocompleteTextareaModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: StreamAutocompleteTextareaModule, declarations: [AutocompleteTextareaComponent], imports: [CommonModule, TranslateModule, MentionModule, StreamAvatarModule], exports: [AutocompleteTextareaComponent] });
2700
+ StreamAutocompleteTextareaModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: StreamAutocompleteTextareaModule, providers: [
2701
+ {
2702
+ provide: textareaInjectionToken,
2703
+ useValue: AutocompleteTextareaComponent,
2704
+ },
2705
+ ], imports: [[CommonModule, TranslateModule, MentionModule, StreamAvatarModule]] });
2706
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: StreamAutocompleteTextareaModule, decorators: [{
2707
+ type: NgModule,
2708
+ args: [{
2709
+ declarations: [AutocompleteTextareaComponent],
2710
+ imports: [CommonModule, TranslateModule, MentionModule, StreamAvatarModule],
2711
+ exports: [AutocompleteTextareaComponent],
2712
+ providers: [
2713
+ {
2714
+ provide: textareaInjectionToken,
2715
+ useValue: AutocompleteTextareaComponent,
2716
+ },
2717
+ ],
2718
+ }]
2719
+ }] });
2720
+
2721
+ class StreamTextareaModule {
2722
+ }
2723
+ StreamTextareaModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: StreamTextareaModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
2724
+ StreamTextareaModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: StreamTextareaModule, declarations: [TextareaComponent], imports: [CommonModule, TranslateModule], exports: [TextareaComponent] });
2725
+ StreamTextareaModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: StreamTextareaModule, providers: [
2726
+ {
2727
+ provide: textareaInjectionToken,
2728
+ useValue: TextareaComponent,
2729
+ },
2730
+ ], imports: [[CommonModule, TranslateModule]] });
2731
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: StreamTextareaModule, decorators: [{
2732
+ type: NgModule,
2733
+ args: [{
2734
+ declarations: [TextareaComponent],
2735
+ imports: [CommonModule, TranslateModule],
2736
+ exports: [TextareaComponent],
2737
+ providers: [
2738
+ {
2739
+ provide: textareaInjectionToken,
2740
+ useValue: TextareaComponent,
2741
+ },
2028
2742
  ],
2029
2743
  }]
2030
2744
  }] });
@@ -2037,5 +2751,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImpor
2037
2751
  * Generated bundle index. Do not edit.
2038
2752
  */
2039
2753
 
2040
- export { AttachmentListComponent, AvatarComponent, ChannelComponent, ChannelHeaderComponent, ChannelListComponent, ChannelListToggleService, ChannelPreviewComponent, ChannelService, ChatClientService, IconComponent, ImageLoadService, LoadingIndicatorComponent, MessageActionsBoxComponent, MessageComponent, MessageInputComponent, MessageListComponent, MessageReactionsComponent, NotificationComponent, NotificationListComponent, StreamChatModule, StreamI18nService, ThemeService, getReadByText, parseDate };
2754
+ export { AttachmentListComponent, AttachmentPreviewListComponent, AttachmentService, AutocompleteTextareaComponent, AvatarComponent, ChannelComponent, ChannelHeaderComponent, ChannelListComponent, ChannelListToggleService, ChannelPreviewComponent, ChannelService, ChatClientService, HighlightMentionsPipe, IconComponent, ImageLoadService, LoadingIndicatorComponent, MessageActionsBoxComponent, MessageComponent, MessageInputComponent, MessageInputConfigService, MessageListComponent, MessageReactionsComponent, ModalComponent, NotificationComponent, NotificationListComponent, NotificationService, StreamAutocompleteTextareaModule, StreamChatModule, StreamI18nService, StreamTextareaModule, TextareaComponent, TextareaDirective, ThemeService, createMessagePreview, getDeviceWidth, getGroupStyles, getReadBy, getReadByText, isImageAttachment, parseDate, textareaInjectionToken };
2041
2755
  //# sourceMappingURL=stream-chat-angular.js.map