stream-chat-angular 2.10.0 → 2.11.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 (32) hide show
  1. package/assets/i18n/en.d.ts +2 -0
  2. package/assets/version.d.ts +1 -1
  3. package/bundles/stream-chat-angular.umd.js +449 -182
  4. package/bundles/stream-chat-angular.umd.js.map +1 -1
  5. package/esm2015/assets/i18n/en.js +3 -1
  6. package/esm2015/assets/version.js +2 -2
  7. package/esm2015/lib/channel/channel.component.js +3 -2
  8. package/esm2015/lib/channel.service.js +158 -40
  9. package/esm2015/lib/icon/icon.component.js +2 -2
  10. package/esm2015/lib/message/message.component.js +18 -3
  11. package/esm2015/lib/message-actions-box/message-actions-box.component.js +1 -1
  12. package/esm2015/lib/message-input/message-input.component.js +32 -8
  13. package/esm2015/lib/message-list/message-list.component.js +100 -53
  14. package/esm2015/lib/message-preview.js +3 -2
  15. package/esm2015/lib/stream-chat.module.js +8 -3
  16. package/esm2015/lib/thread/thread.component.js +37 -0
  17. package/esm2015/public-api.js +2 -1
  18. package/fesm2015/stream-chat-angular.js +351 -108
  19. package/fesm2015/stream-chat-angular.js.map +1 -1
  20. package/lib/channel/channel.component.d.ts +2 -1
  21. package/lib/channel.service.d.ts +18 -7
  22. package/lib/icon/icon.component.d.ts +1 -1
  23. package/lib/message/message.component.d.ts +7 -1
  24. package/lib/message-input/message-input.component.d.ts +4 -1
  25. package/lib/message-list/message-list.component.d.ts +12 -3
  26. package/lib/message-preview.d.ts +1 -1
  27. package/lib/stream-chat.module.d.ts +5 -4
  28. package/lib/thread/thread.component.d.ts +18 -0
  29. package/package.json +2 -2
  30. package/public-api.d.ts +1 -0
  31. package/src/assets/i18n/en.ts +4 -0
  32. package/src/assets/version.ts +1 -1
@@ -1,9 +1,9 @@
1
1
  import { __awaiter } from 'tslib';
2
2
  import * as i0 from '@angular/core';
3
3
  import { Injectable, Component, Input, InjectionToken, EventEmitter, Directive, Output, Inject, ViewChild, HostBinding, NgModule } from '@angular/core';
4
- import { BehaviorSubject, ReplaySubject, of, Subject } from 'rxjs';
4
+ import { BehaviorSubject, ReplaySubject, combineLatest, of, Subject } from 'rxjs';
5
5
  import { StreamChat } from 'stream-chat';
6
- import { map, first, catchError, startWith, distinctUntilChanged, filter, debounceTime, tap } from 'rxjs/operators';
6
+ import { map, shareReplay, filter, first, catchError, startWith, distinctUntilChanged, debounceTime, tap } from 'rxjs/operators';
7
7
  import { v4 } from 'uuid';
8
8
  import * as i10 from '@ngx-translate/core';
9
9
  import { TranslateModule } from '@ngx-translate/core';
@@ -16,7 +16,7 @@ import transliterate from '@stream-io/transliterate';
16
16
  import * as i5 from 'angular-mentions';
17
17
  import { MentionModule } from 'angular-mentions';
18
18
 
19
- const version = '2.10.0';
19
+ const version = '2.11.0';
20
20
 
21
21
  class NotificationService {
22
22
  constructor() {
@@ -149,7 +149,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImpor
149
149
  }]
150
150
  }], ctorParameters: function () { return [{ type: i0.NgZone }, { type: NotificationService }]; } });
151
151
 
152
- const createMessagePreview = (user, text, attachments, mentionedUsers) => {
152
+ const createMessagePreview = (user, text, attachments, mentionedUsers, parentId) => {
153
153
  const clientSideId = `${user.id}-${v4()}`;
154
154
  return {
155
155
  __html: text,
@@ -163,6 +163,7 @@ const createMessagePreview = (user, text, attachments, mentionedUsers) => {
163
163
  user,
164
164
  attachments,
165
165
  mentioned_users: mentionedUsers,
166
+ parent_id: parentId,
166
167
  };
167
168
  };
168
169
 
@@ -188,31 +189,50 @@ class ChannelService {
188
189
  this.activeChannelMessagesSubject = new BehaviorSubject([]);
189
190
  this.hasMoreChannelsSubject = new ReplaySubject(1);
190
191
  this.activeChannelSubscriptions = [];
192
+ this.activeParentMessageIdSubject = new BehaviorSubject(undefined);
193
+ this.activeThreadMessagesSubject = new BehaviorSubject([]);
194
+ this.messagePageSize = 25;
191
195
  this.channelListSetter = (channels) => {
192
196
  this.channelsSubject.next(channels);
193
197
  };
194
198
  this.messageListSetter = (messages) => {
195
199
  this.activeChannelMessagesSubject.next(messages);
196
200
  };
201
+ this.threadListSetter = (messages) => {
202
+ this.activeThreadMessagesSubject.next(messages);
203
+ };
204
+ this.parentMessageSetter = (message) => {
205
+ this.activeParentMessageIdSubject.next(message === null || message === void 0 ? void 0 : message.id);
206
+ };
197
207
  this.channels$ = this.channelsSubject.asObservable();
198
208
  this.activeChannel$ = this.activeChannelSubject.asObservable();
199
209
  this.activeChannelMessages$ = this.activeChannelMessagesSubject.pipe(map((messages) => {
200
210
  const channel = this.activeChannelSubject.getValue();
201
- return messages.map((message) => {
202
- if (this.isStreamMessage(message) &&
203
- this.isFormatMessageResponse(message)) {
204
- return message;
205
- }
206
- else if (this.isFormatMessageResponse(message)) {
207
- return Object.assign(Object.assign({}, message), { readBy: getReadBy(message, channel) });
208
- }
209
- else {
210
- const formatMessage = this.formatMessage(message);
211
- return Object.assign(Object.assign({}, formatMessage), { readBy: getReadBy(formatMessage, channel) });
212
- }
213
- });
211
+ return messages.map((message) => this.transformToStreamMessage(message, channel));
214
212
  }));
215
213
  this.hasMoreChannels$ = this.hasMoreChannelsSubject.asObservable();
214
+ this.activeParentMessageId$ =
215
+ this.activeParentMessageIdSubject.asObservable();
216
+ this.activeThreadMessages$ = this.activeThreadMessagesSubject.pipe(map((messages) => {
217
+ const channel = this.activeChannelSubject.getValue();
218
+ return messages.map((message) => this.transformToStreamMessage(message, channel));
219
+ }));
220
+ this.activeParentMessage$ = combineLatest([
221
+ this.activeChannelMessages$,
222
+ this.activeParentMessageId$,
223
+ ]).pipe(map(([messages, parentMessageId]) => {
224
+ if (!parentMessageId) {
225
+ return undefined;
226
+ }
227
+ else {
228
+ return messages.find((m) => m.id === parentMessageId);
229
+ }
230
+ }), shareReplay());
231
+ this.chatClientService.connectionState$
232
+ .pipe(filter((s) => s === 'online'))
233
+ .subscribe(() => {
234
+ void this.setAsActiveParentMessage(undefined);
235
+ });
216
236
  }
217
237
  setAsActiveChannel(channel) {
218
238
  const prevActiveChannel = this.activeChannelSubject.getValue();
@@ -226,25 +246,61 @@ class ChannelService {
226
246
  void channel.markRead();
227
247
  }
228
248
  this.activeChannelMessagesSubject.next([...channel.state.messages]);
249
+ this.activeParentMessageIdSubject.next(undefined);
250
+ this.activeThreadMessagesSubject.next([]);
251
+ }
252
+ setAsActiveParentMessage(message) {
253
+ var _a;
254
+ return __awaiter(this, void 0, void 0, function* () {
255
+ if (!message) {
256
+ this.activeParentMessageIdSubject.next(undefined);
257
+ this.activeThreadMessagesSubject.next([]);
258
+ }
259
+ else {
260
+ this.activeParentMessageIdSubject.next(message.id);
261
+ const activeChannel = this.activeChannelSubject.getValue();
262
+ const result = yield (activeChannel === null || activeChannel === void 0 ? void 0 : activeChannel.getReplies(message.id, {
263
+ limit: (_a = this.options) === null || _a === void 0 ? void 0 : _a.message_limit,
264
+ }));
265
+ this.activeThreadMessagesSubject.next((result === null || result === void 0 ? void 0 : result.messages) || []);
266
+ }
267
+ });
229
268
  }
269
+ // load more thread replies
230
270
  loadMoreMessages() {
231
- var _a, _b, _c, _d;
271
+ var _a, _b, _c, _d, _e;
232
272
  return __awaiter(this, void 0, void 0, function* () {
233
273
  const activeChnannel = this.activeChannelSubject.getValue();
234
274
  const lastMessageId = (_a = this.activeChannelMessagesSubject.getValue()[0]) === null || _a === void 0 ? void 0 : _a.id;
235
275
  yield (activeChnannel === null || activeChnannel === void 0 ? void 0 : activeChnannel.query({
236
- messages: { limit: 25, id_lt: lastMessageId },
276
+ messages: { limit: (_b = this.options) === null || _b === void 0 ? void 0 : _b.message_limit, id_lt: lastMessageId },
237
277
  members: { limit: 0 },
238
278
  watchers: { limit: 0 },
239
279
  }));
240
- if (((_b = activeChnannel === null || activeChnannel === void 0 ? void 0 : activeChnannel.data) === null || _b === void 0 ? void 0 : _b.id) ===
241
- ((_d = (_c = this.activeChannelSubject.getValue()) === null || _c === void 0 ? void 0 : _c.data) === null || _d === void 0 ? void 0 : _d.id)) {
280
+ if (((_c = activeChnannel === null || activeChnannel === void 0 ? void 0 : activeChnannel.data) === null || _c === void 0 ? void 0 : _c.id) ===
281
+ ((_e = (_d = this.activeChannelSubject.getValue()) === null || _d === void 0 ? void 0 : _d.data) === null || _e === void 0 ? void 0 : _e.id)) {
242
282
  this.activeChannelMessagesSubject.next([
243
283
  ...activeChnannel.state.messages,
244
284
  ]);
245
285
  }
246
286
  });
247
287
  }
288
+ loadMoreThreadReplies() {
289
+ var _a, _b;
290
+ return __awaiter(this, void 0, void 0, function* () {
291
+ const activeChnannel = this.activeChannelSubject.getValue();
292
+ const parentMessageId = this.activeParentMessageIdSubject.getValue();
293
+ if (!parentMessageId) {
294
+ return;
295
+ }
296
+ const lastMessageId = (_a = this.activeThreadMessagesSubject.getValue()[0]) === null || _a === void 0 ? void 0 : _a.id;
297
+ yield (activeChnannel === null || activeChnannel === void 0 ? void 0 : activeChnannel.getReplies(parentMessageId, {
298
+ limit: (_b = this.options) === null || _b === void 0 ? void 0 : _b.message_limit,
299
+ id_lt: lastMessageId,
300
+ }));
301
+ this.activeThreadMessagesSubject.next((activeChnannel === null || activeChnannel === void 0 ? void 0 : activeChnannel.state.threads[parentMessageId]) || []);
302
+ });
303
+ }
248
304
  init(filters, sort, options) {
249
305
  return __awaiter(this, void 0, void 0, function* () {
250
306
  this.filters = filters;
@@ -254,7 +310,7 @@ class ChannelService {
254
310
  state: true,
255
311
  presence: true,
256
312
  watch: true,
257
- message_limit: 25,
313
+ message_limit: this.messagePageSize,
258
314
  };
259
315
  this.sort = sort || { last_message_at: -1, updated_at: -1 };
260
316
  yield this.queryChannels();
@@ -264,6 +320,8 @@ class ChannelService {
264
320
  reset() {
265
321
  this.activeChannelMessagesSubject.next([]);
266
322
  this.activeChannelSubject.next(undefined);
323
+ this.activeParentMessageIdSubject.next(undefined);
324
+ this.activeThreadMessagesSubject.next([]);
267
325
  this.channelsSubject.next(undefined);
268
326
  }
269
327
  loadMoreChannels() {
@@ -287,9 +345,9 @@ class ChannelService {
287
345
  .getValue()) === null || _a === void 0 ? void 0 : _a.deleteReaction(messageId, reactionType));
288
346
  });
289
347
  }
290
- sendMessage(text, attachments = [], mentionedUsers = []) {
348
+ sendMessage(text, attachments = [], mentionedUsers = [], parentId = undefined) {
291
349
  return __awaiter(this, void 0, void 0, function* () {
292
- const preview = createMessagePreview(this.chatClientService.chatClient.user, text, attachments, mentionedUsers);
350
+ const preview = createMessagePreview(this.chatClientService.chatClient.user, text, attachments, mentionedUsers, parentId);
293
351
  const channel = this.activeChannelSubject.getValue();
294
352
  preview.readBy = [];
295
353
  channel.state.addMessageSorted(preview, true);
@@ -373,11 +431,25 @@ class ChannelService {
373
431
  const response = yield channel.sendAction(messageId, formData);
374
432
  if (response === null || response === void 0 ? void 0 : response.message) {
375
433
  channel.state.addMessageSorted(Object.assign(Object.assign({}, response.message), { status: 'received' }));
376
- this.activeChannelMessagesSubject.next([...channel.state.messages]);
434
+ const isThreadReply = !!response.message.parent_id;
435
+ isThreadReply
436
+ ? this.activeThreadMessagesSubject.next([
437
+ ...channel.state.threads[response.message.parent_id],
438
+ ])
439
+ : this.activeChannelMessagesSubject.next([...channel.state.messages]);
377
440
  }
378
441
  else {
379
442
  channel.state.removeMessage({ id: messageId });
380
- this.activeChannelMessagesSubject.next([...channel.state.messages]);
443
+ if (this.activeChannelMessagesSubject
444
+ .getValue()
445
+ .find((m) => m.id === messageId)) {
446
+ this.activeChannelMessagesSubject.next([...channel.state.messages]);
447
+ }
448
+ else if (this.activeThreadMessagesSubject
449
+ .getValue()
450
+ .find((m) => m.id === messageId)) {
451
+ this.activeThreadMessagesSubject.next(channel.state.threads[this.activeParentMessageIdSubject.getValue()]);
452
+ }
381
453
  }
382
454
  });
383
455
  }
@@ -385,17 +457,27 @@ class ChannelService {
385
457
  var _a;
386
458
  return __awaiter(this, void 0, void 0, function* () {
387
459
  const channel = this.activeChannelSubject.getValue();
388
- this.activeChannelMessagesSubject.next([...channel.state.messages]);
460
+ const isThreadReply = !!preview.parent_id;
461
+ isThreadReply
462
+ ? this.activeThreadMessagesSubject.next([
463
+ ...channel.state.threads[preview.parent_id],
464
+ ])
465
+ : this.activeChannelMessagesSubject.next([...channel.state.messages]);
389
466
  try {
390
467
  const response = yield channel.sendMessage({
391
468
  text: preview.text,
392
469
  attachments: preview.attachments,
393
470
  mentioned_users: (_a = preview.mentioned_users) === null || _a === void 0 ? void 0 : _a.map((u) => u.id),
394
471
  id: preview.id,
472
+ parent_id: preview.parent_id,
395
473
  });
396
474
  if (response === null || response === void 0 ? void 0 : response.message) {
397
475
  channel.state.addMessageSorted(Object.assign(Object.assign({}, response.message), { status: 'received' }), true);
398
- this.activeChannelMessagesSubject.next([...channel.state.messages]);
476
+ isThreadReply
477
+ ? this.activeThreadMessagesSubject.next([
478
+ ...channel.state.threads[preview.parent_id],
479
+ ])
480
+ : this.activeChannelMessagesSubject.next([...channel.state.messages]);
399
481
  }
400
482
  }
401
483
  catch (error) {
@@ -404,7 +486,11 @@ class ChannelService {
404
486
  ? JSON.parse(stringError)
405
487
  : {};
406
488
  channel.state.addMessageSorted(Object.assign(Object.assign({}, preview), { errorStatusCode: parsedError.status || undefined, status: 'failed' }), true);
407
- this.activeChannelMessagesSubject.next([...channel.state.messages]);
489
+ isThreadReply
490
+ ? this.activeThreadMessagesSubject.next([
491
+ ...channel.state.threads[preview.parent_id],
492
+ ])
493
+ : this.activeChannelMessagesSubject.next([...channel.state.messages]);
408
494
  }
409
495
  });
410
496
  }
@@ -482,9 +568,15 @@ class ChannelService {
482
568
  }
483
569
  }
484
570
  watchForActiveChannelEvents(channel) {
485
- this.activeChannelSubscriptions.push(channel.on('message.new', () => {
571
+ this.activeChannelSubscriptions.push(channel.on('message.new', (event) => {
486
572
  this.ngZone.run(() => {
487
- this.activeChannelMessagesSubject.next([...channel.state.messages]);
573
+ event.message && event.message.parent_id
574
+ ? this.activeThreadMessagesSubject.next([
575
+ ...channel.state.threads[event.message.parent_id],
576
+ ])
577
+ : this.activeChannelMessagesSubject.next([
578
+ ...channel.state.messages,
579
+ ]);
488
580
  this.activeChannel$.pipe(first()).subscribe((c) => {
489
581
  if (this.canSendReadEvents) {
490
582
  void (c === null || c === void 0 ? void 0 : c.markRead());
@@ -513,19 +605,27 @@ class ChannelService {
513
605
  }
514
606
  messageUpdated(event) {
515
607
  this.ngZone.run(() => {
516
- const messages = this.activeChannelMessagesSubject.getValue();
608
+ const isThreadReply = event.message && event.message.parent_id;
609
+ const messages = isThreadReply
610
+ ? this.activeThreadMessagesSubject.getValue()
611
+ : this.activeChannelMessagesSubject.getValue();
517
612
  const messageIndex = messages.findIndex((m) => { var _a; return m.id === ((_a = event.message) === null || _a === void 0 ? void 0 : _a.id); });
518
613
  if (messageIndex !== -1 && event.message) {
519
614
  messages[messageIndex] = event.message;
520
- this.activeChannelMessagesSubject.next([...messages]);
615
+ isThreadReply
616
+ ? this.activeThreadMessagesSubject.next([...messages])
617
+ : this.activeChannelMessagesSubject.next([...messages]);
521
618
  }
522
619
  });
523
620
  }
524
621
  messageReactionEventReceived(e) {
525
622
  this.ngZone.run(() => {
526
623
  var _a, _b, _c, _d;
624
+ const isThreadMessage = e.message && e.message.parent_id;
527
625
  let messages;
528
- this.activeChannelMessages$
626
+ (isThreadMessage
627
+ ? this.activeThreadMessages$
628
+ : this.activeChannelMessages$)
529
629
  .pipe(first())
530
630
  .subscribe((m) => (messages = m));
531
631
  const message = messages.find((m) => { var _a; return m.id === ((_a = e === null || e === void 0 ? void 0 : e.message) === null || _a === void 0 ? void 0 : _a.id); });
@@ -536,7 +636,9 @@ class ChannelService {
536
636
  message.reaction_scores = Object.assign({}, (_b = e.message) === null || _b === void 0 ? void 0 : _b.reaction_scores);
537
637
  message.latest_reactions = [...(((_c = e.message) === null || _c === void 0 ? void 0 : _c.latest_reactions) || [])];
538
638
  message.own_reactions = [...(((_d = e.message) === null || _d === void 0 ? void 0 : _d.own_reactions) || [])];
539
- this.activeChannelMessagesSubject.next([...messages]);
639
+ isThreadMessage
640
+ ? this.activeThreadMessagesSubject.next([...messages])
641
+ : this.activeChannelMessagesSubject.next([...messages]);
540
642
  });
541
643
  }
542
644
  formatMessage(message) {
@@ -584,7 +686,7 @@ class ChannelService {
584
686
  case 'message.new': {
585
687
  this.ngZone.run(() => {
586
688
  if (this.customNewMessageHandler) {
587
- this.customNewMessageHandler(event, channel, this.channelListSetter, this.messageListSetter);
689
+ this.customNewMessageHandler(event, channel, this.channelListSetter, this.messageListSetter, this.threadListSetter, this.parentMessageSetter);
588
690
  }
589
691
  else {
590
692
  this.handleNewMessage(event, channel);
@@ -595,7 +697,7 @@ class ChannelService {
595
697
  case 'channel.hidden': {
596
698
  this.ngZone.run(() => {
597
699
  if (this.customChannelHiddenHandler) {
598
- this.customChannelHiddenHandler(event, channel, this.channelListSetter, this.messageListSetter);
700
+ this.customChannelHiddenHandler(event, channel, this.channelListSetter, this.messageListSetter, this.threadListSetter, this.parentMessageSetter);
599
701
  }
600
702
  else {
601
703
  this.handleChannelHidden(event);
@@ -606,7 +708,7 @@ class ChannelService {
606
708
  case 'channel.deleted': {
607
709
  this.ngZone.run(() => {
608
710
  if (this.customChannelDeletedHandler) {
609
- this.customChannelDeletedHandler(event, channel, this.channelListSetter, this.messageListSetter);
711
+ this.customChannelDeletedHandler(event, channel, this.channelListSetter, this.messageListSetter, this.threadListSetter, this.parentMessageSetter);
610
712
  }
611
713
  else {
612
714
  this.handleChannelDeleted(event);
@@ -617,7 +719,7 @@ class ChannelService {
617
719
  case 'channel.visible': {
618
720
  this.ngZone.run(() => {
619
721
  if (this.customChannelVisibleHandler) {
620
- this.customChannelVisibleHandler(event, channel, this.channelListSetter, this.messageListSetter);
722
+ this.customChannelVisibleHandler(event, channel, this.channelListSetter, this.messageListSetter, this.threadListSetter, this.parentMessageSetter);
621
723
  }
622
724
  else {
623
725
  this.handleChannelVisible(event, channel);
@@ -628,7 +730,7 @@ class ChannelService {
628
730
  case 'channel.updated': {
629
731
  this.ngZone.run(() => {
630
732
  if (this.customChannelUpdatedHandler) {
631
- this.customChannelUpdatedHandler(event, channel, this.channelListSetter, this.messageListSetter);
733
+ this.customChannelUpdatedHandler(event, channel, this.channelListSetter, this.messageListSetter, this.threadListSetter, this.parentMessageSetter);
632
734
  }
633
735
  else {
634
736
  this.handleChannelUpdate(event);
@@ -639,7 +741,7 @@ class ChannelService {
639
741
  case 'channel.truncated': {
640
742
  this.ngZone.run(() => {
641
743
  if (this.customChannelTruncatedHandler) {
642
- this.customChannelTruncatedHandler(event, channel, this.channelListSetter, this.messageListSetter);
744
+ this.customChannelTruncatedHandler(event, channel, this.channelListSetter, this.messageListSetter, this.threadListSetter, this.parentMessageSetter);
643
745
  }
644
746
  else {
645
747
  this.handleChannelTruncate(event);
@@ -679,6 +781,7 @@ class ChannelService {
679
781
  }
680
782
  }
681
783
  }
784
+ // truncate active thread as well
682
785
  handleChannelTruncate(event) {
683
786
  var _a, _b;
684
787
  const channelIndex = this.channels.findIndex((c) => c.cid === event.channel.cid);
@@ -690,6 +793,8 @@ class ChannelService {
690
793
  channel.state.messages = [];
691
794
  this.activeChannelSubject.next(channel);
692
795
  this.activeChannelMessagesSubject.next([]);
796
+ this.activeParentMessageIdSubject.next(undefined);
797
+ this.activeThreadMessagesSubject.next([]);
693
798
  }
694
799
  }
695
800
  }
@@ -705,6 +810,20 @@ class ChannelService {
705
810
  const capabilites = (_a = channel.data) === null || _a === void 0 ? void 0 : _a.own_capabilities;
706
811
  return capabilites.indexOf('read-events') !== -1;
707
812
  }
813
+ transformToStreamMessage(message, channel) {
814
+ const isThreadMessage = !!message.parent_id;
815
+ if (this.isStreamMessage(message) &&
816
+ this.isFormatMessageResponse(message)) {
817
+ return message;
818
+ }
819
+ else if (this.isFormatMessageResponse(message)) {
820
+ return Object.assign(Object.assign({}, message), { readBy: isThreadMessage ? [] : getReadBy(message, channel) });
821
+ }
822
+ else {
823
+ const formatMessage = this.formatMessage(message);
824
+ return Object.assign(Object.assign({}, formatMessage), { readBy: isThreadMessage ? [] : getReadBy(formatMessage, channel) });
825
+ }
826
+ }
708
827
  }
709
828
  ChannelService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: ChannelService, deps: [{ token: ChatClientService }, { token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Injectable });
710
829
  ChannelService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: ChannelService, providedIn: 'root' });
@@ -1017,6 +1136,7 @@ const en = {
1017
1136
  Flag: 'Flag',
1018
1137
  'Message Failed': 'Message Failed',
1019
1138
  'Message Failed · Unauthorized': 'Message Failed · Unauthorized',
1139
+ 'Message Failed · Click to try again': 'Message Failed · Click to try again',
1020
1140
  'Message deleted': 'Message deleted',
1021
1141
  'Message has been successfully flagged': 'Message has been successfully flagged',
1022
1142
  'Message pinned': 'Message pinned',
@@ -1067,6 +1187,7 @@ const en = {
1067
1187
  test: 'success',
1068
1188
  'Sending links is not allowed in this conversation': 'Sending links is not allowed in this conversation',
1069
1189
  "You can't send messages in this channel": "You can't send messages in this channel",
1190
+ "You can't send thread replies in this channel": "You can't send thread replies in this channel",
1070
1191
  'Unsupported file type: {{type}}': 'Unsupported file type: {{type}}',
1071
1192
  },
1072
1193
  };
@@ -1123,7 +1244,7 @@ class IconComponent {
1123
1244
  constructor() { }
1124
1245
  }
1125
1246
  IconComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: IconComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1126
- 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: i6.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i10.TranslateDirective, selector: "[translate],[ngx-translate]", inputs: ["translate", "translateParams"] }] });
1247
+ 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<svg\n *ngIf=\"icon === 'reply'\"\n data-testid=\"reply\"\n height=\"15\"\n width=\"18\"\n xmlns=\"http://www.w3.org/2000/svg\"\n>\n <path\n d=\"M.56 10.946H.06l-.002-.498L.025.92a.5.5 0 1 1 1-.004l.032 9.029H9.06v-4l9 4.5-9 4.5v-4H.56z\"\n fillRule=\"nonzero\"\n />\n</svg>\n<svg\n data-testid=\"close-no-outline\"\n *ngIf=\"icon === 'close-no-outline'\"\n height=\"10\"\n width=\"10\"\n xmlns=\"http://www.w3.org/2000/svg\"\n>\n <path\n d=\"M9.916 1.027L8.973.084 5 4.058 1.027.084l-.943.943L4.058 5 .084 8.973l.943.943L5 5.942l3.973 3.974.943-.943L5.942 5z\"\n fillRule=\"evenodd\"\n />\n</svg>\n<svg\n height=\"10\"\n width=\"14\"\n xmlns=\"http://www.w3.org/2000/svg\"\n data-testid=\"reply-in-thread\"\n *ngIf=\"icon === 'reply-in-thread'\"\n>\n <path\n d=\"M8.516 3c4.78 0 4.972 6.5 4.972 6.5-1.6-2.906-2.847-3.184-4.972-3.184v2.872L3.772 4.994 8.516.5V3zM.484 5l4.5-4.237v1.78L2.416 5l2.568 2.125v1.828L.484 5z\"\n fillRule=\"evenodd\"\n />\n</svg>\n", directives: [{ type: i6.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i10.TranslateDirective, selector: "[translate],[ngx-translate]", inputs: ["translate", "translateParams"] }] });
1127
1248
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: IconComponent, decorators: [{
1128
1249
  type: Component,
1129
1250
  args: [{
@@ -1301,6 +1422,7 @@ class MessageInputComponent {
1301
1422
  this.componentFactoryResolver = componentFactoryResolver;
1302
1423
  this.cdRef = cdRef;
1303
1424
  this.chatClient = chatClient;
1425
+ this.mode = 'main';
1304
1426
  this.messageUpdate = new EventEmitter();
1305
1427
  this.textareaValue = '';
1306
1428
  this.mentionedUsers = [];
@@ -1321,11 +1443,8 @@ class MessageInputComponent {
1321
1443
  this.isFileUploadAuthorized =
1322
1444
  capabilities.indexOf('upload-file') !== -1;
1323
1445
  this.canSendLinks = capabilities.indexOf('send-links') !== -1;
1324
- this.canSendMessages = capabilities.indexOf('send-message') !== -1;
1325
- if (this.isViewInited) {
1326
- this.cdRef.detectChanges();
1327
- this.initTextarea();
1328
- }
1446
+ this.channel = channel;
1447
+ this.setCanSendMessages();
1329
1448
  }
1330
1449
  }));
1331
1450
  this.subscriptions.push(this.chatClient.appSettings$.subscribe((appSettings) => (this.appSettings = appSettings)));
@@ -1377,6 +1496,9 @@ class MessageInputComponent {
1377
1496
  if (changes.mentionScope) {
1378
1497
  this.configService.mentionScope = this.mentionScope;
1379
1498
  }
1499
+ if (changes.mode) {
1500
+ this.setCanSendMessages();
1501
+ }
1380
1502
  }
1381
1503
  ngOnDestroy() {
1382
1504
  this.subscriptions.forEach((s) => s.unsubscribe());
@@ -1406,10 +1528,16 @@ class MessageInputComponent {
1406
1528
  if (!this.isUpdate) {
1407
1529
  this.textareaValue = '';
1408
1530
  }
1531
+ let parentMessageId = undefined;
1532
+ if (this.mode === 'thread') {
1533
+ this.channelService.activeParentMessageId$
1534
+ .pipe(first())
1535
+ .subscribe((id) => (parentMessageId = id));
1536
+ }
1409
1537
  try {
1410
1538
  yield (this.isUpdate
1411
1539
  ? this.channelService.updateMessage(Object.assign(Object.assign({}, this.message), { text: text, attachments: attachments }))
1412
- : this.channelService.sendMessage(text, attachments, this.mentionedUsers));
1540
+ : this.channelService.sendMessage(text, attachments, this.mentionedUsers, parentMessageId));
1413
1541
  this.messageUpdate.emit();
1414
1542
  if (!this.isUpdate) {
1415
1543
  this.attachmentService.resetAttachmentUploads();
@@ -1503,9 +1631,24 @@ class MessageInputComponent {
1503
1631
  return isValid;
1504
1632
  });
1505
1633
  }
1634
+ setCanSendMessages() {
1635
+ var _a, _b;
1636
+ const capabilities = (_b = (_a = this.channel) === null || _a === void 0 ? void 0 : _a.data) === null || _b === void 0 ? void 0 : _b.own_capabilities;
1637
+ if (!capabilities) {
1638
+ this.canSendMessages = false;
1639
+ }
1640
+ else {
1641
+ this.canSendMessages =
1642
+ capabilities.indexOf(this.mode === 'main' ? 'send-message' : 'send-reply') !== -1;
1643
+ }
1644
+ if (this.isViewInited) {
1645
+ this.cdRef.detectChanges();
1646
+ this.initTextarea();
1647
+ }
1648
+ }
1506
1649
  }
1507
1650
  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 }, { token: i0.ChangeDetectorRef }, { token: ChatClientService }], target: i0.ɵɵFactoryTarget.Component });
1508
- 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", commandAutocompleteItemTemplate: "commandAutocompleteItemTemplate", 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 }], 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 *ngIf=\"canSendMessages; else notAllowed\"\n streamTextarea\n [(value)]=\"textareaValue\"\n (send)=\"messageSent()\"\n [componentRef]=\"textareaRef\"\n (userMentions)=\"mentionedUsers = $event\"\n [areMentionsEnabled]=\"areMentionsEnabled\"\n [mentionAutocompleteItemTemplate]=\"mentionAutocompleteItemTemplate\"\n [commandAutocompleteItemTemplate]=\"commandAutocompleteItemTemplate\"\n [mentionScope]=\"mentionScope\"\n ></ng-template>\n <ng-template #notAllowed>\n <textarea\n disabled\n rows=\"1\"\n [value]=\"\n 'streamChat.You can\\'t send messages in this channel' | translate\n \"\n class=\"rta__textarea str-chat__textarea__textarea\"\n ></textarea>\n </ng-template>\n </div>\n <div\n *ngIf=\"isFileUploadEnabled && isFileUploadAuthorized && canSendMessages\"\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 *ngIf=\"canSendMessages\"\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: i6.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: TextareaDirective, selector: "[streamTextarea]", inputs: ["componentRef", "areMentionsEnabled", "mentionAutocompleteItemTemplate", "mentionScope", "commandAutocompleteItemTemplate", "value"], outputs: ["valueChange", "send", "userMentions"] }], pipes: { "async": i6.AsyncPipe, "translate": i10.TranslatePipe } });
1651
+ 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", commandAutocompleteItemTemplate: "commandAutocompleteItemTemplate", mode: "mode", 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 }], usesOnChanges: true, ngImport: i0, template: "<div\n class=\"{{\n mode === 'main' ? 'str-chat__input-flat' : 'str-chat__small-message-input'\n }}\"\n [class.str-chat__input-flat-has-attachments]=\"\n (attachmentUploads$ | async)!.length > 0\n \"\n>\n <div class=\"str-chat__input-flat-wrapper\" style=\"width: 100%\">\n <div\n class=\"{{\n mode === 'main'\n ? 'str-chat__input-flat--textarea-wrapper'\n : 'str-chat__small-message-input--textarea-wrapper'\n }}\"\n >\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 *ngIf=\"canSendMessages; else notAllowed\"\n streamTextarea\n [(value)]=\"textareaValue\"\n (send)=\"messageSent()\"\n [componentRef]=\"textareaRef\"\n (userMentions)=\"mentionedUsers = $event\"\n [areMentionsEnabled]=\"areMentionsEnabled\"\n [mentionAutocompleteItemTemplate]=\"mentionAutocompleteItemTemplate\"\n [commandAutocompleteItemTemplate]=\"commandAutocompleteItemTemplate\"\n [mentionScope]=\"mentionScope\"\n ></ng-template>\n <ng-template #notAllowed>\n <textarea\n disabled\n rows=\"1\"\n [value]=\"\n (mode === 'thread'\n ? 'You can\\'t send thread replies in this channel'\n : 'streamChat.You can\\'t send messages in this channel'\n ) | translate\n \"\n class=\"rta__textarea str-chat__textarea__textarea\"\n ></textarea>\n </ng-template>\n </div>\n <div\n *ngIf=\"isFileUploadEnabled && isFileUploadAuthorized && canSendMessages\"\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 *ngIf=\"canSendMessages\"\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: i6.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: TextareaDirective, selector: "[streamTextarea]", inputs: ["componentRef", "areMentionsEnabled", "mentionAutocompleteItemTemplate", "mentionScope", "commandAutocompleteItemTemplate", "value"], outputs: ["valueChange", "send", "userMentions"] }], pipes: { "async": i6.AsyncPipe, "translate": i10.TranslatePipe } });
1509
1652
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: MessageInputComponent, decorators: [{
1510
1653
  type: Component,
1511
1654
  args: [{
@@ -1527,6 +1670,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImpor
1527
1670
  type: Input
1528
1671
  }], commandAutocompleteItemTemplate: [{
1529
1672
  type: Input
1673
+ }], mode: [{
1674
+ type: Input
1530
1675
  }], acceptedFileTypes: [{
1531
1676
  type: Input
1532
1677
  }], isMultipleFileUploadEnabled: [{
@@ -1746,7 +1891,7 @@ class MessageActionsBoxComponent {
1746
1891
  }
1747
1892
  }
1748
1893
  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 });
1749
- MessageActionsBoxComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.5", type: MessageActionsBoxComponent, selector: "stream-message-actions-box", inputs: { messageInputTemplate: "messageInputTemplate", 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 <ng-container *ngIf=\"messageInputTemplate; else defaultInput\">\n <ng-container\n *ngTemplateOutlet=\"\n messageInputTemplate;\n context: {\n message: message,\n messageUpdateHandler: modalClosed\n }\n \"\n ></ng-container>\n </ng-container>\n <ng-template #defaultInput>\n <stream-message-input\n [message]=\"message\"\n (messageUpdate)=\"modalClosed()\"\n ></stream-message-input>\n </ng-template>\n <stream-notification-list></stream-notification-list>\n <div\n class=\"\n str-chat__message-team-form-footer\n str-chat__message-team-form-footer-angular\n \"\n >\n <div class=\"str-chat__edit-message-form-options\">\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", "commandAutocompleteItemTemplate", "acceptedFileTypes", "isMultipleFileUploadEnabled", "message"], outputs: ["messageUpdate"] }, { type: NotificationListComponent, selector: "stream-notification-list" }], directives: [{ type: i6.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i6.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet"] }, { type: i10.TranslateDirective, selector: "[translate],[ngx-translate]", inputs: ["translate", "translateParams"] }], pipes: { "translate": i10.TranslatePipe } });
1894
+ MessageActionsBoxComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.5", type: MessageActionsBoxComponent, selector: "stream-message-actions-box", inputs: { messageInputTemplate: "messageInputTemplate", 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 <ng-container *ngIf=\"messageInputTemplate; else defaultInput\">\n <ng-container\n *ngTemplateOutlet=\"\n messageInputTemplate;\n context: {\n message: message,\n messageUpdateHandler: modalClosed\n }\n \"\n ></ng-container>\n </ng-container>\n <ng-template #defaultInput>\n <stream-message-input\n [message]=\"message\"\n (messageUpdate)=\"modalClosed()\"\n ></stream-message-input>\n </ng-template>\n <stream-notification-list></stream-notification-list>\n <div\n class=\"\n str-chat__message-team-form-footer\n str-chat__message-team-form-footer-angular\n \"\n >\n <div class=\"str-chat__edit-message-form-options\">\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", "commandAutocompleteItemTemplate", "mode", "acceptedFileTypes", "isMultipleFileUploadEnabled", "message"], outputs: ["messageUpdate"] }, { type: NotificationListComponent, selector: "stream-notification-list" }], directives: [{ type: i6.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i6.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet"] }, { type: i10.TranslateDirective, selector: "[translate],[ngx-translate]", inputs: ["translate", "translateParams"] }], pipes: { "translate": i10.TranslatePipe } });
1750
1895
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: MessageActionsBoxComponent, decorators: [{
1751
1896
  type: Component,
1752
1897
  args: [{
@@ -1779,10 +1924,11 @@ class ChannelComponent {
1779
1924
  this.subscriptions = [];
1780
1925
  this.isError$ = this.channelService.channels$.pipe(map(() => false), catchError(() => of(true)), startWith(false));
1781
1926
  this.isInitializing$ = this.channelService.channels$.pipe(map((channels) => !channels), catchError(() => of(false)));
1927
+ this.isActiveThread$ = this.channelService.activeParentMessageId$.pipe(map((id) => !!id));
1782
1928
  }
1783
1929
  }
1784
1930
  ChannelComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: ChannelComponent, deps: [{ token: ChannelService }], target: i0.ɵɵFactoryTarget.Component });
1785
- ChannelComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.5", type: ChannelComponent, selector: "stream-channel", ngImport: i0, template: "<div\n *ngIf=\"(isError$ | async) === false && (isInitializing$ | async) === false\"\n class=\"str-chat str-chat-channel messaging\"\n>\n <div class=\"str-chat__container\">\n <div class=\"str-chat__main-panel\">\n <ng-content></ng-content>\n </div>\n </div>\n</div>\n", directives: [{ type: i6.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }], pipes: { "async": i6.AsyncPipe } });
1931
+ ChannelComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.5", type: ChannelComponent, selector: "stream-channel", ngImport: i0, template: "<div\n *ngIf=\"(isError$ | async) === false && (isInitializing$ | async) === false\"\n class=\"str-chat str-chat-channel messaging\"\n>\n <div class=\"str-chat__container\">\n <div class=\"str-chat__main-panel\">\n <ng-content></ng-content>\n </div>\n <ng-content\n *ngIf=\"isActiveThread$ | async\"\n select='[name=\"thread\"]'\n ></ng-content>\n </div>\n</div>\n", directives: [{ type: i6.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }], pipes: { "async": i6.AsyncPipe } });
1786
1932
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: ChannelComponent, decorators: [{
1787
1933
  type: Component,
1788
1934
  args: [{
@@ -2276,6 +2422,7 @@ class MessageComponent {
2276
2422
  this.chatClientService = chatClientService;
2277
2423
  this.channelService = channelService;
2278
2424
  this.enabledMessageActions = [];
2425
+ this.mode = 'main';
2279
2426
  this.isActionBoxOpen = false;
2280
2427
  this.isReactionSelectorOpen = false;
2281
2428
  this.isPressedOnMobile = false;
@@ -2365,7 +2512,8 @@ class MessageComponent {
2365
2512
  this.message.type === 'system' ||
2366
2513
  this.message.type === 'ephemeral' ||
2367
2514
  this.message.status === 'failed' ||
2368
- this.message.status === 'sending');
2515
+ this.message.status === 'sending' ||
2516
+ (this.mode === 'thread' && !this.message.parent_id));
2369
2517
  }
2370
2518
  get hasAttachment() {
2371
2519
  var _a;
@@ -2376,6 +2524,14 @@ class MessageComponent {
2376
2524
  return (!!((_a = this.message) === null || _a === void 0 ? void 0 : _a.reaction_counts) &&
2377
2525
  Object.keys(this.message.reaction_counts).length > 0);
2378
2526
  }
2527
+ get replyCountParam() {
2528
+ var _a;
2529
+ return { replyCount: (_a = this.message) === null || _a === void 0 ? void 0 : _a.reply_count };
2530
+ }
2531
+ get canDisplayReadStatus() {
2532
+ return (this.canReceiveReadEvents !== false &&
2533
+ this.enabledMessageActions.indexOf('read-events') !== -1);
2534
+ }
2379
2535
  resendMessage() {
2380
2536
  void this.channelService.resendMessage(this.message);
2381
2537
  }
@@ -2397,9 +2553,12 @@ class MessageComponent {
2397
2553
  };
2398
2554
  window.addEventListener('click', eventHandler);
2399
2555
  }
2556
+ setAsActiveParentMessage() {
2557
+ void this.channelService.setAsActiveParentMessage(this.message);
2558
+ }
2400
2559
  }
2401
2560
  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 });
2402
- MessageComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.5", type: MessageComponent, selector: "stream-message", inputs: { messageInputTemplate: "messageInputTemplate", mentionTemplate: "mentionTemplate", message: "message", enabledMessageActions: "enabledMessageActions", areReactionsEnabled: "areReactionsEnabled", canReactToMessage: "canReactToMessage", isLastSentMessage: "isLastSentMessage", canReceiveReadEvents: "canReceiveReadEvents" }, viewQueries: [{ propertyName: "container", first: true, predicate: ["container"], descendants: true }], usesOnChanges: 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 !== false && 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\n *ngIf=\"\n isMessageDeliveredAndRead &&\n canReceiveReadEvents !== false &&\n enabledMessageActions.indexOf('read-events') !== -1;\n else deliveredStatus\n \"\n >\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 [messageInputTemplate]=\"messageInputTemplate\"\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 <!-- eslint-disable @angular-eslint/template/conditional-complexity -->\n <div\n *ngIf=\"\n areReactionsEnabled !== false &&\n canReactToMessage !== false &&\n enabledMessageActions.indexOf('send-reaction') !== -1\n \"\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 <!-- eslint-enable @angular-eslint/template/conditional-complexity -->\n <stream-message-reactions\n *ngIf=\"areReactionsEnabled !== false\"\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 [messageId]=\"message!.id\"\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 >\n <p>\n <!-- eslint-disable-next-line @angular-eslint/template/use-track-by-function -->\n <ng-container *ngFor=\"let part of messageTextParts\">\n <span\n *ngIf=\"part.type === 'text'; else mention\"\n [innerHTML]=\"part.content\"\n ></span>\n <ng-template #mention>\n <ng-container *ngIf=\"mentionTemplate; else defaultMention\">\n <ng-container\n *ngTemplateOutlet=\"\n mentionTemplate;\n context: { user: part.user! }\n \"\n ></ng-container>\n </ng-container>\n <ng-template #defaultMention>\n <b>{{ part.content }}</b>\n </ng-template>\n </ng-template>\n </ng-container>\n </p>\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\n class=\"\n str-chat__message-simple-status str-chat__message-simple-status-angular\n \"\n data-testid=\"sending-indicator\"\n >\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\n class=\"\n str-chat__message-simple-status str-chat__message-simple-status-angular\n \"\n data-testid=\"read-indicator\"\n >\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=\"\n str-chat__message-simple-status str-chat__message-simple-status-angular\n \"\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: ["messageInputTemplate", "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: ["messageId", "attachments"] }, { type: LoadingIndicatorComponent, selector: "stream-loading-indicator", inputs: ["size", "color"] }], directives: [{ type: i6.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i6.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet"] }, { type: i6.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i10.TranslateDirective, selector: "[translate],[ngx-translate]", inputs: ["translate", "translateParams"] }], pipes: { "translate": i10.TranslatePipe } });
2561
+ MessageComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.5", type: MessageComponent, selector: "stream-message", inputs: { messageInputTemplate: "messageInputTemplate", mentionTemplate: "mentionTemplate", message: "message", enabledMessageActions: "enabledMessageActions", areReactionsEnabled: "areReactionsEnabled", canReactToMessage: "canReactToMessage", isLastSentMessage: "isLastSentMessage", canReceiveReadEvents: "canReceiveReadEvents", mode: "mode" }, viewQueries: [{ propertyName: "container", first: true, predicate: ["container"], descendants: true }], usesOnChanges: 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 !== false && 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\n *ngIf=\"\n mode === 'main' &&\n isMessageDeliveredAndRead &&\n canDisplayReadStatus;\n else deliveredStatus\n \"\n >\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 [messageInputTemplate]=\"messageInputTemplate\"\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 <!-- eslint-disable @angular-eslint/template/conditional-complexity -->\n <div\n *ngIf=\"\n enabledMessageActions.indexOf('send-reply') !== -1 &&\n mode === 'main'\n \"\n class=\"\n str-chat__message-simple__actions__action\n str-chat__message-simple__actions__action--thread\n \"\n data-testid=\"reply-in-thread\"\n (click)=\"setAsActiveParentMessage()\"\n (keyup.enter)=\"setAsActiveParentMessage()\"\n >\n <stream-icon icon=\"reply-in-thread\"></stream-icon>\n </div>\n <div\n *ngIf=\"\n areReactionsEnabled !== false &&\n canReactToMessage !== false &&\n enabledMessageActions.indexOf('send-reaction') !== -1\n \"\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 <!-- eslint-enable @angular-eslint/template/conditional-complexity -->\n <stream-message-reactions\n *ngIf=\"areReactionsEnabled !== false\"\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 [messageId]=\"message!.id\"\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 >\n <p>\n <!-- eslint-disable-next-line @angular-eslint/template/use-track-by-function -->\n <ng-container *ngFor=\"let part of messageTextParts\">\n <span\n *ngIf=\"part.type === 'text'; else mention\"\n [innerHTML]=\"part.content\"\n ></span>\n <ng-template #mention>\n <ng-container *ngIf=\"mentionTemplate; else defaultMention\">\n <ng-container\n *ngTemplateOutlet=\"\n mentionTemplate;\n context: { user: part.user! }\n \"\n ></ng-container>\n </ng-container>\n <ng-template #defaultMention>\n <b>{{ part.content }}</b>\n </ng-template>\n </ng-template>\n </ng-container>\n </p>\n </div>\n </div>\n </div>\n <div class=\"str-chat__message-simple-reply-button\">\n <button\n *ngIf=\"\n !!message?.reply_count &&\n mode !== 'thread' &&\n enabledMessageActions.indexOf('send-reply') !== -1\n \"\n class=\"str-chat__message-replies-count-button\"\n data-testid=\"reply-count-button\"\n (click)=\"setAsActiveParentMessage()\"\n >\n <stream-icon icon=\"reply\"></stream-icon>\n {{message?.reply_count === 1 ? ('streamChat.1 reply' | translate) : ('streamChat.{{ replyCount }}\n replies' | translate:replyCountParam)}}\n </button>\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\n class=\"\n str-chat__message-simple-status str-chat__message-simple-status-angular\n \"\n data-testid=\"sending-indicator\"\n >\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\n class=\"\n str-chat__message-simple-status str-chat__message-simple-status-angular\n \"\n data-testid=\"read-indicator\"\n >\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 *ngIf=\"mode === 'main'\"\n class=\"\n str-chat__message-simple-status str-chat__message-simple-status-angular\n \"\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: ["messageInputTemplate", "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: ["messageId", "attachments"] }, { type: LoadingIndicatorComponent, selector: "stream-loading-indicator", inputs: ["size", "color"] }], directives: [{ type: i6.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i6.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet"] }, { type: i6.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i10.TranslateDirective, selector: "[translate],[ngx-translate]", inputs: ["translate", "translateParams"] }], pipes: { "translate": i10.TranslatePipe } });
2403
2562
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: MessageComponent, decorators: [{
2404
2563
  type: Component,
2405
2564
  args: [{
@@ -2423,6 +2582,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImpor
2423
2582
  type: Input
2424
2583
  }], canReceiveReadEvents: [{
2425
2584
  type: Input
2585
+ }], mode: [{
2586
+ type: Input
2426
2587
  }], container: [{
2427
2588
  type: ViewChild,
2428
2589
  args: ['container']
@@ -2716,22 +2877,17 @@ class MessageListComponent {
2716
2877
  */
2717
2878
  /* eslint-disable-next-line @angular-eslint/no-input-rename */
2718
2879
  this.enabledMessageActionsInput = undefined;
2880
+ this.mode = 'main';
2719
2881
  this.enabledMessageActions = [];
2720
2882
  this.class = 'str-chat-angular__main-panel-inner str-chat-angular__message-list-host';
2721
2883
  this.unreadMessageCount = 0;
2722
2884
  this.groupStyles = [];
2723
2885
  this.authorizedMessageActions = ['flag'];
2724
2886
  this.isUserScrolledUpThreshold = 300;
2725
- this.channelService.activeChannel$.subscribe((channel) => {
2887
+ this.subscriptions = [];
2888
+ this.subscriptions.push(this.channelService.activeChannel$.subscribe((channel) => {
2726
2889
  var _a;
2727
- this.latestMessageDate = undefined;
2728
- this.hasNewMessages = true;
2729
- this.isUserScrolledUp = false;
2730
- this.containerHeight = undefined;
2731
- this.olderMassagesLoaded = false;
2732
- this.oldestMessageDate = undefined;
2733
- this.unreadMessageCount = 0;
2734
- this.isNewMessageSentByUser = undefined;
2890
+ this.resetScrollState();
2735
2891
  const capabilites = (_a = channel === null || channel === void 0 ? void 0 : channel.data) === null || _a === void 0 ? void 0 : _a.own_capabilities;
2736
2892
  if (capabilites) {
2737
2893
  this.canReactToMessage = capabilites.indexOf('send-reaction') !== -1;
@@ -2760,47 +2916,13 @@ class MessageListComponent {
2760
2916
  this.authorizedMessageActions.push('delete');
2761
2917
  this.authorizedMessageActions.push('delete-any');
2762
2918
  }
2763
- this.setEnabledActions();
2764
- }
2765
- });
2766
- this.messages$ = this.channelService.activeChannelMessages$.pipe(tap((messages) => {
2767
- var _a, _b, _c, _d, _e;
2768
- if (messages.length === 0) {
2769
- return;
2770
- }
2771
- const currentLatestMessageDate = messages[messages.length - 1].created_at;
2772
- if (!this.latestMessageDate ||
2773
- ((_a = this.latestMessageDate) === null || _a === void 0 ? void 0 : _a.getTime()) < currentLatestMessageDate.getTime()) {
2774
- this.latestMessageDate = currentLatestMessageDate;
2775
- this.hasNewMessages = true;
2776
- this.isNewMessageSentByUser =
2777
- ((_b = messages[messages.length - 1].user) === null || _b === void 0 ? void 0 : _b.id) ===
2778
- ((_d = (_c = this.chatClientService.chatClient) === null || _c === void 0 ? void 0 : _c.user) === null || _d === void 0 ? void 0 : _d.id);
2779
- if (this.isUserScrolledUp) {
2780
- this.unreadMessageCount++;
2919
+ if (capabilites.indexOf('send-reply') !== -1) {
2920
+ this.authorizedMessageActions.push('send-reply');
2781
2921
  }
2922
+ this.setEnabledActions();
2782
2923
  }
2783
- const currentOldestMessageDate = messages[0].created_at;
2784
- if (!this.oldestMessageDate) {
2785
- this.oldestMessageDate = currentOldestMessageDate;
2786
- }
2787
- else if (((_e = this.oldestMessageDate) === null || _e === void 0 ? void 0 : _e.getTime()) > currentOldestMessageDate.getTime()) {
2788
- this.oldestMessageDate = currentOldestMessageDate;
2789
- this.olderMassagesLoaded = true;
2790
- }
2791
- }), tap((messages) => {
2792
- this.groupStyles = messages.map((m, i) => getGroupStyles(m, messages[i - 1], messages[i + 1]));
2793
- }), tap((messages) => {
2794
- var _a;
2795
- return (this.lastSentMessageId = (_a = [...messages]
2796
- .reverse()
2797
- .find((m) => {
2798
- var _a, _b, _c;
2799
- return ((_a = m.user) === null || _a === void 0 ? void 0 : _a.id) === ((_c = (_b = this.chatClientService.chatClient) === null || _b === void 0 ? void 0 : _b.user) === null || _c === void 0 ? void 0 : _c.id) &&
2800
- m.status !== 'sending';
2801
- })) === null || _a === void 0 ? void 0 : _a.id);
2802
2924
  }));
2803
- this.imageLoadService.imageLoad$.subscribe(() => {
2925
+ this.subscriptions.push(this.imageLoadService.imageLoad$.subscribe(() => {
2804
2926
  if (!this.isUserScrolledUp) {
2805
2927
  this.scrollToBottom();
2806
2928
  // Hacky and unreliable workaround to scroll down after loaded images move the scrollbar
@@ -2808,12 +2930,27 @@ class MessageListComponent {
2808
2930
  this.scrollToBottom();
2809
2931
  }, 300);
2810
2932
  }
2811
- });
2933
+ }));
2934
+ this.subscriptions.push(this.channelService.activeParentMessage$.subscribe((message) => {
2935
+ if (message &&
2936
+ this.parentMessage &&
2937
+ message.id !== this.parentMessage.id &&
2938
+ this.mode === 'thread') {
2939
+ this.resetScrollState();
2940
+ }
2941
+ this.parentMessage = message;
2942
+ }));
2943
+ }
2944
+ ngOnInit() {
2945
+ this.setMessages$();
2812
2946
  }
2813
2947
  ngOnChanges(changes) {
2814
2948
  if (changes.enabledMessageActionsInput) {
2815
2949
  this.setEnabledActions();
2816
2950
  }
2951
+ if (changes.mode) {
2952
+ this.setMessages$();
2953
+ }
2817
2954
  }
2818
2955
  ngAfterViewChecked() {
2819
2956
  if (this.hasNewMessages) {
@@ -2839,6 +2976,9 @@ class MessageListComponent {
2839
2976
  this.containerHeight = this.scrollContainer.nativeElement.scrollHeight;
2840
2977
  }
2841
2978
  }
2979
+ ngOnDestroy() {
2980
+ this.subscriptions.forEach((s) => s.unsubscribe());
2981
+ }
2842
2982
  trackByMessageId(index, item) {
2843
2983
  return item.id;
2844
2984
  }
@@ -2847,6 +2987,7 @@ class MessageListComponent {
2847
2987
  this.scrollContainer.nativeElement.scrollHeight;
2848
2988
  }
2849
2989
  scrolled() {
2990
+ var _a, _b;
2850
2991
  this.isUserScrolledUp =
2851
2992
  this.scrollContainer.nativeElement.scrollHeight -
2852
2993
  (this.scrollContainer.nativeElement.scrollTop +
@@ -2855,14 +2996,22 @@ class MessageListComponent {
2855
2996
  if (!this.isUserScrolledUp) {
2856
2997
  this.unreadMessageCount = 0;
2857
2998
  }
2858
- if (this.scrollContainer.nativeElement.scrollTop === 0) {
2999
+ if (this.scrollContainer.nativeElement.scrollTop <=
3000
+ (((_a = this.parentMessageElement) === null || _a === void 0 ? void 0 : _a.nativeElement.clientHeight) || 0) &&
3001
+ (this.prevScrollTop === undefined ||
3002
+ this.prevScrollTop >
3003
+ (((_b = this.parentMessageElement) === null || _b === void 0 ? void 0 : _b.nativeElement.clientHeight) || 0))) {
2859
3004
  this.containerHeight = this.scrollContainer.nativeElement.scrollHeight;
2860
- void this.channelService.loadMoreMessages();
3005
+ this.mode === 'main'
3006
+ ? void this.channelService.loadMoreMessages()
3007
+ : void this.channelService.loadMoreThreadReplies();
2861
3008
  }
3009
+ this.prevScrollTop = this.scrollContainer.nativeElement.scrollTop;
2862
3010
  }
2863
3011
  preserveScrollbarPosition() {
2864
3012
  this.scrollContainer.nativeElement.scrollTop =
2865
- this.scrollContainer.nativeElement.scrollHeight - this.containerHeight;
3013
+ (this.prevScrollTop || 0) +
3014
+ (this.scrollContainer.nativeElement.scrollHeight - this.containerHeight);
2866
3015
  }
2867
3016
  setEnabledActions() {
2868
3017
  this.enabledMessageActions = [];
@@ -2874,6 +3023,7 @@ class MessageListComponent {
2874
3023
  ...this.enabledMessageActionsInput,
2875
3024
  'send-reaction',
2876
3025
  'read-events',
3026
+ 'send-reply',
2877
3027
  ];
2878
3028
  this.enabledMessageActionsInput.forEach((action) => {
2879
3029
  const isAuthorized = this.authorizedMessageActions.indexOf(action) !== -1;
@@ -2882,9 +3032,61 @@ class MessageListComponent {
2882
3032
  }
2883
3033
  });
2884
3034
  }
3035
+ setMessages$() {
3036
+ this.messages$ = (this.mode === 'main'
3037
+ ? this.channelService.activeChannelMessages$
3038
+ : this.channelService.activeThreadMessages$).pipe(tap((messages) => {
3039
+ var _a, _b, _c, _d, _e;
3040
+ if (messages.length === 0) {
3041
+ return;
3042
+ }
3043
+ const currentLatestMessageDate = messages[messages.length - 1].created_at;
3044
+ if (!this.latestMessageDate ||
3045
+ ((_a = this.latestMessageDate) === null || _a === void 0 ? void 0 : _a.getTime()) < currentLatestMessageDate.getTime()) {
3046
+ this.latestMessageDate = currentLatestMessageDate;
3047
+ this.hasNewMessages = true;
3048
+ this.isNewMessageSentByUser =
3049
+ ((_b = messages[messages.length - 1].user) === null || _b === void 0 ? void 0 : _b.id) ===
3050
+ ((_d = (_c = this.chatClientService.chatClient) === null || _c === void 0 ? void 0 : _c.user) === null || _d === void 0 ? void 0 : _d.id);
3051
+ if (this.isUserScrolledUp) {
3052
+ this.unreadMessageCount++;
3053
+ }
3054
+ }
3055
+ const currentOldestMessageDate = messages[0].created_at;
3056
+ if (!this.oldestMessageDate) {
3057
+ this.oldestMessageDate = currentOldestMessageDate;
3058
+ }
3059
+ else if (((_e = this.oldestMessageDate) === null || _e === void 0 ? void 0 : _e.getTime()) > currentOldestMessageDate.getTime()) {
3060
+ this.oldestMessageDate = currentOldestMessageDate;
3061
+ this.olderMassagesLoaded = true;
3062
+ }
3063
+ }), tap((messages) => {
3064
+ this.groupStyles = messages.map((m, i) => getGroupStyles(m, messages[i - 1], messages[i + 1]));
3065
+ }), tap((messages) => {
3066
+ var _a;
3067
+ return (this.lastSentMessageId = (_a = [...messages]
3068
+ .reverse()
3069
+ .find((m) => {
3070
+ var _a, _b, _c;
3071
+ return ((_a = m.user) === null || _a === void 0 ? void 0 : _a.id) === ((_c = (_b = this.chatClientService.chatClient) === null || _b === void 0 ? void 0 : _b.user) === null || _c === void 0 ? void 0 : _c.id) &&
3072
+ m.status !== 'sending';
3073
+ })) === null || _a === void 0 ? void 0 : _a.id);
3074
+ }));
3075
+ }
3076
+ resetScrollState() {
3077
+ this.latestMessageDate = undefined;
3078
+ this.hasNewMessages = true;
3079
+ this.isUserScrolledUp = false;
3080
+ this.containerHeight = undefined;
3081
+ this.olderMassagesLoaded = false;
3082
+ this.oldestMessageDate = undefined;
3083
+ this.unreadMessageCount = 0;
3084
+ this.prevScrollTop = undefined;
3085
+ this.isNewMessageSentByUser = undefined;
3086
+ }
2885
3087
  }
2886
3088
  MessageListComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: MessageListComponent, deps: [{ token: ChannelService }, { token: ChatClientService }, { token: ImageLoadService }], target: i0.ɵɵFactoryTarget.Component });
2887
- MessageListComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.5", type: MessageListComponent, selector: "stream-message-list", inputs: { messageTemplate: "messageTemplate", messageInputTemplate: "messageInputTemplate", mentionTemplate: "mentionTemplate", areReactionsEnabled: "areReactionsEnabled", enabledMessageActionsInput: ["enabledMessageActions", "enabledMessageActionsInput"] }, host: { properties: { "class": "this.class" } }, viewQueries: [{ propertyName: "scrollContainer", first: true, predicate: ["scrollContainer"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div\n #scrollContainer\n data-testid=\"scroll-container\"\n class=\"str-chat__list\"\n (scroll)=\"scrolled()\"\n>\n <div class=\"str-chat__reverse-infinite-scroll\">\n <ul class=\"str-chat__ul\">\n <li\n data-testclass=\"message\"\n *ngFor=\"\n let message of messages$ | async;\n let i = index;\n trackBy: trackByMessageId\n \"\n class=\"str-chat__li str-chat__li--{{ groupStyles[i] }}\"\n >\n <ng-container *ngIf=\"messageTemplate; else defaultMessageTemplate\">\n <ng-container\n *ngTemplateOutlet=\"\n messageTemplate;\n context: {\n message: message,\n areReactionsEnabled: areReactionsEnabled,\n canReactToMessage: canReactToMessage,\n lastSentMessageId: !!(\n lastSentMessageId && message?.id === lastSentMessageId\n ),\n canReceiveReadEvents: canReceiveReadEvents,\n messageInputTemplate: messageInputTemplate,\n mentionTemplate: mentionTemplate\n }\n \"\n ></ng-container>\n </ng-container>\n <ng-template #defaultMessageTemplate>\n <stream-message\n [message]=\"message\"\n [areReactionsEnabled]=\"areReactionsEnabled\"\n [canReactToMessage]=\"canReactToMessage\"\n [isLastSentMessage]=\"\n !!(lastSentMessageId && message?.id === lastSentMessageId)\n \"\n [enabledMessageActions]=\"enabledMessageActions\"\n [canReceiveReadEvents]=\"canReceiveReadEvents\"\n [messageInputTemplate]=\"messageInputTemplate\"\n [mentionTemplate]=\"mentionTemplate\"\n ></stream-message>\n </ng-template>\n </li>\n </ul>\n </div>\n</div>\n<div class=\"str-chat__list-notifications\">\n <button\n data-testid=\"scroll-to-bottom\"\n *ngIf=\"isUserScrolledUp\"\n class=\"\n str-chat__message-notification\n str-chat__message-notification-right\n str-chat__message-notification-scroll-down\n \"\n (keyup.enter)=\"scrollToBottom()\"\n (click)=\"scrollToBottom()\"\n >\n <div\n *ngIf=\"unreadMessageCount > 0\"\n class=\"\n str-chat__message-notification\n str-chat__message-notification-scroll-down-unread-count\n \"\n >\n {{ unreadMessageCount }}\n </div>\n </button>\n</div>\n", components: [{ type: MessageComponent, selector: "stream-message", inputs: ["messageInputTemplate", "mentionTemplate", "message", "enabledMessageActions", "areReactionsEnabled", "canReactToMessage", "isLastSentMessage", "canReceiveReadEvents"] }], directives: [{ type: i6.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i6.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i6.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet"] }], pipes: { "async": i6.AsyncPipe } });
3089
+ MessageListComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.5", type: MessageListComponent, selector: "stream-message-list", inputs: { messageTemplate: "messageTemplate", messageInputTemplate: "messageInputTemplate", mentionTemplate: "mentionTemplate", areReactionsEnabled: "areReactionsEnabled", enabledMessageActionsInput: ["enabledMessageActions", "enabledMessageActionsInput"], mode: "mode" }, host: { properties: { "class": "this.class" } }, viewQueries: [{ propertyName: "scrollContainer", first: true, predicate: ["scrollContainer"], descendants: true }, { propertyName: "parentMessageElement", first: true, predicate: ["parentMessageElement"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div\n #scrollContainer\n data-testid=\"scroll-container\"\n class=\"str-chat__list\"\n (scroll)=\"scrolled()\"\n>\n <div class=\"str-chat__reverse-infinite-scroll\">\n <ul class=\"str-chat__ul\">\n <li\n #parentMessageElement\n *ngIf=\"mode === 'thread'\"\n data-testid=\"parent-message\"\n >\n <ng-container\n *ngTemplateOutlet=\"\n messageTemplateContainer;\n context: { message: parentMessage }\n \"\n ></ng-container>\n <div class=\"str-chat__thread-start\" translate>\n streamChat.Start of a new thread\n </div>\n </li>\n <li\n data-testclass=\"message\"\n *ngFor=\"\n let message of messages$ | async;\n let i = index;\n trackBy: trackByMessageId\n \"\n class=\"str-chat__li str-chat__li--{{ groupStyles[i] }}\"\n >\n <ng-container\n *ngTemplateOutlet=\"\n messageTemplateContainer;\n context: { message: message }\n \"\n ></ng-container>\n </li>\n </ul>\n </div>\n</div>\n<div class=\"str-chat__list-notifications\">\n <button\n data-testid=\"scroll-to-bottom\"\n *ngIf=\"isUserScrolledUp\"\n class=\"\n str-chat__message-notification\n str-chat__message-notification-right\n str-chat__message-notification-scroll-down\n \"\n (keyup.enter)=\"scrollToBottom()\"\n (click)=\"scrollToBottom()\"\n >\n <div\n *ngIf=\"unreadMessageCount > 0\"\n class=\"\n str-chat__message-notification\n str-chat__message-notification-scroll-down-unread-count\n \"\n >\n {{ unreadMessageCount }}\n </div>\n </button>\n</div>\n\n<ng-template #messageTemplateContainer let-message=\"message\">\n <ng-container *ngIf=\"messageTemplate; else defaultMessageTemplate\">\n <ng-container\n *ngTemplateOutlet=\"\n messageTemplate;\n context: {\n message: message,\n areReactionsEnabled: areReactionsEnabled,\n canReactToMessage: canReactToMessage,\n lastSentMessageId: !!(\n lastSentMessageId && message?.id === lastSentMessageId\n ),\n canReceiveReadEvents: canReceiveReadEvents,\n messageInputTemplate: messageInputTemplate,\n mentionTemplate: mentionTemplate,\n mode: mode\n }\n \"\n ></ng-container>\n </ng-container>\n <ng-template #defaultMessageTemplate>\n <stream-message\n [message]=\"message\"\n [areReactionsEnabled]=\"areReactionsEnabled\"\n [canReactToMessage]=\"canReactToMessage\"\n [isLastSentMessage]=\"\n !!(lastSentMessageId && message?.id === lastSentMessageId)\n \"\n [enabledMessageActions]=\"enabledMessageActions\"\n [canReceiveReadEvents]=\"canReceiveReadEvents\"\n [messageInputTemplate]=\"messageInputTemplate\"\n [mentionTemplate]=\"mentionTemplate\"\n [mode]=\"mode\"\n ></stream-message>\n </ng-template>\n</ng-template>\n", components: [{ type: MessageComponent, selector: "stream-message", inputs: ["messageInputTemplate", "mentionTemplate", "message", "enabledMessageActions", "areReactionsEnabled", "canReactToMessage", "isLastSentMessage", "canReceiveReadEvents", "mode"] }], directives: [{ type: i6.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i6.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet"] }, { type: i10.TranslateDirective, selector: "[translate],[ngx-translate]", inputs: ["translate", "translateParams"] }, { type: i6.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }], pipes: { "async": i6.AsyncPipe } });
2888
3090
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: MessageListComponent, decorators: [{
2889
3091
  type: Component,
2890
3092
  args: [{
@@ -2903,12 +3105,49 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImpor
2903
3105
  }], enabledMessageActionsInput: [{
2904
3106
  type: Input,
2905
3107
  args: ['enabledMessageActions']
3108
+ }], mode: [{
3109
+ type: Input
2906
3110
  }], class: [{
2907
3111
  type: HostBinding,
2908
3112
  args: ['class']
2909
3113
  }], scrollContainer: [{
2910
3114
  type: ViewChild,
2911
3115
  args: ['scrollContainer']
3116
+ }], parentMessageElement: [{
3117
+ type: ViewChild,
3118
+ args: ['parentMessageElement']
3119
+ }] } });
3120
+
3121
+ class ThreadComponent {
3122
+ constructor(channelService) {
3123
+ this.channelService = channelService;
3124
+ this.class = 'str-chat__thread';
3125
+ this.subscriptions = [];
3126
+ this.subscriptions.push(this.channelService.activeParentMessage$.subscribe((parentMessage) => (this.parentMessage = parentMessage)));
3127
+ }
3128
+ ngOnDestroy() {
3129
+ this.subscriptions.forEach((s) => s.unsubscribe());
3130
+ }
3131
+ get replyCountParam() {
3132
+ var _a;
3133
+ return { replyCount: (_a = this.parentMessage) === null || _a === void 0 ? void 0 : _a.reply_count };
3134
+ }
3135
+ closeThread() {
3136
+ void this.channelService.setAsActiveParentMessage(undefined);
3137
+ }
3138
+ }
3139
+ ThreadComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: ThreadComponent, deps: [{ token: ChannelService }], target: i0.ɵɵFactoryTarget.Component });
3140
+ ThreadComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.5", type: ThreadComponent, selector: "stream-thread", host: { properties: { "class": "this.class" } }, ngImport: i0, template: "<div class=\"str-chat__thread-header\">\n <div class=\"str-chat__thread-header-details\">\n <strong translate>streamChat.Thread</strong>\n <small data-testid=\"reply-count\">\n {{parentMessage?.reply_count === 1 ? ('streamChat.1 reply' | translate) : ('streamChat.{{ replyCount }}\n replies' | translate:replyCountParam)}}\n </small>\n </div>\n <button\n class=\"str-chat__square-button\"\n data-testid=\"close-button\"\n (click)=\"closeThread()\"\n >\n <stream-icon icon=\"close-no-outline\"></stream-icon>\n </button>\n</div>\n<ng-content select='[name=\"thread-message-list\"]'></ng-content>\n<div class=\"str-chat__small-message-input__wrapper\">\n <ng-content select='[name=\"thread-message-input\"]'></ng-content>\n</div>\n", components: [{ type: IconComponent, selector: "stream-icon", inputs: ["icon", "size"] }], directives: [{ type: i10.TranslateDirective, selector: "[translate],[ngx-translate]", inputs: ["translate", "translateParams"] }], pipes: { "translate": i10.TranslatePipe } });
3141
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: ThreadComponent, decorators: [{
3142
+ type: Component,
3143
+ args: [{
3144
+ selector: 'stream-thread',
3145
+ templateUrl: './thread.component.html',
3146
+ styles: [],
3147
+ }]
3148
+ }], ctorParameters: function () { return [{ type: ChannelService }]; }, propDecorators: { class: [{
3149
+ type: HostBinding,
3150
+ args: ['class']
2912
3151
  }] } });
2913
3152
 
2914
3153
  class StreamAvatarModule {
@@ -2944,7 +3183,8 @@ StreamChatModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "12.0.0", versio
2944
3183
  NotificationListComponent,
2945
3184
  AttachmentPreviewListComponent,
2946
3185
  ModalComponent,
2947
- TextareaDirective], imports: [CommonModule, TranslateModule, StreamAvatarModule], exports: [ChannelComponent,
3186
+ TextareaDirective,
3187
+ ThreadComponent], imports: [CommonModule, TranslateModule, StreamAvatarModule], exports: [ChannelComponent,
2948
3188
  ChannelHeaderComponent,
2949
3189
  ChannelListComponent,
2950
3190
  ChannelPreviewComponent,
@@ -2960,7 +3200,8 @@ StreamChatModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "12.0.0", versio
2960
3200
  NotificationListComponent,
2961
3201
  AttachmentPreviewListComponent,
2962
3202
  ModalComponent,
2963
- StreamAvatarModule] });
3203
+ StreamAvatarModule,
3204
+ ThreadComponent] });
2964
3205
  StreamChatModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: StreamChatModule, imports: [[CommonModule, TranslateModule, StreamAvatarModule], StreamAvatarModule] });
2965
3206
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: StreamChatModule, decorators: [{
2966
3207
  type: NgModule,
@@ -2983,6 +3224,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImpor
2983
3224
  AttachmentPreviewListComponent,
2984
3225
  ModalComponent,
2985
3226
  TextareaDirective,
3227
+ ThreadComponent,
2986
3228
  ],
2987
3229
  imports: [CommonModule, TranslateModule, StreamAvatarModule],
2988
3230
  exports: [
@@ -3003,6 +3245,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImpor
3003
3245
  AttachmentPreviewListComponent,
3004
3246
  ModalComponent,
3005
3247
  StreamAvatarModule,
3248
+ ThreadComponent,
3006
3249
  ],
3007
3250
  }]
3008
3251
  }] });
@@ -3065,5 +3308,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImpor
3065
3308
  * Generated bundle index. Do not edit.
3066
3309
  */
3067
3310
 
3068
- export { AttachmentListComponent, AttachmentPreviewListComponent, AttachmentService, AutocompleteTextareaComponent, AvatarComponent, ChannelComponent, ChannelHeaderComponent, ChannelListComponent, ChannelListToggleService, ChannelPreviewComponent, ChannelService, ChatClientService, IconComponent, ImageLoadService, LoadingIndicatorComponent, MessageActionsBoxComponent, MessageComponent, MessageInputComponent, MessageInputConfigService, MessageListComponent, MessageReactionsComponent, ModalComponent, NotificationComponent, NotificationListComponent, NotificationService, StreamAutocompleteTextareaModule, StreamAvatarModule, StreamChatModule, StreamI18nService, StreamTextareaModule, TextareaComponent, TextareaDirective, ThemeService, TransliterationService, createMessagePreview, getDeviceWidth, getGroupStyles, getReadBy, getReadByText, isImageAttachment, isImageFile, parseDate, textareaInjectionToken };
3311
+ export { AttachmentListComponent, AttachmentPreviewListComponent, AttachmentService, AutocompleteTextareaComponent, AvatarComponent, ChannelComponent, ChannelHeaderComponent, ChannelListComponent, ChannelListToggleService, ChannelPreviewComponent, ChannelService, ChatClientService, IconComponent, ImageLoadService, LoadingIndicatorComponent, MessageActionsBoxComponent, MessageComponent, MessageInputComponent, MessageInputConfigService, MessageListComponent, MessageReactionsComponent, ModalComponent, NotificationComponent, NotificationListComponent, NotificationService, StreamAutocompleteTextareaModule, StreamAvatarModule, StreamChatModule, StreamI18nService, StreamTextareaModule, TextareaComponent, TextareaDirective, ThemeService, ThreadComponent, TransliterationService, createMessagePreview, getDeviceWidth, getGroupStyles, getReadBy, getReadByText, isImageAttachment, isImageFile, parseDate, textareaInjectionToken };
3069
3312
  //# sourceMappingURL=stream-chat-angular.js.map