stream-chat-angular 5.1.10 → 5.2.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 (43) hide show
  1. package/assets/version.d.ts +1 -1
  2. package/esm2020/assets/version.mjs +2 -2
  3. package/esm2020/lib/attachment-list/attachment-list.component.mjs +3 -3
  4. package/esm2020/lib/channel-header/channel-header.component.mjs +3 -3
  5. package/esm2020/lib/channel-list/channel-list.component.mjs +3 -3
  6. package/esm2020/lib/channel-preview/channel-preview.component.mjs +3 -3
  7. package/esm2020/lib/channel.service.mjs +3 -1
  8. package/esm2020/lib/chat-client.service.mjs +1 -1
  9. package/esm2020/lib/message/message.component.mjs +12 -5
  10. package/esm2020/lib/message-actions-box/message-actions-box.component.mjs +3 -3
  11. package/esm2020/lib/message-input/autocomplete-textarea/autocomplete-textarea.component.mjs +3 -3
  12. package/esm2020/lib/message-input/message-input.component.mjs +3 -3
  13. package/esm2020/lib/message-input/textarea/textarea.component.mjs +3 -3
  14. package/esm2020/lib/message-list/message-list.component.mjs +3 -3
  15. package/esm2020/lib/message-reactions/message-reactions.component.mjs +72 -80
  16. package/esm2020/lib/message-reactions-selector/message-reactions-selector.component.mjs +3 -3
  17. package/esm2020/lib/message-reactions.service.mjs +30 -4
  18. package/esm2020/lib/notification-list/notification-list.component.mjs +3 -3
  19. package/esm2020/lib/paginated-list/paginated-list.component.mjs +94 -0
  20. package/esm2020/lib/stream-chat.module.mjs +13 -3
  21. package/esm2020/lib/types.mjs +1 -1
  22. package/esm2020/lib/user-list/user-list.component.mjs +47 -0
  23. package/esm2020/lib/voice-recording/voice-recording.component.mjs +3 -3
  24. package/esm2020/public-api.mjs +3 -1
  25. package/fesm2015/stream-chat-angular.mjs +290 -116
  26. package/fesm2015/stream-chat-angular.mjs.map +1 -1
  27. package/fesm2020/stream-chat-angular.mjs +275 -107
  28. package/fesm2020/stream-chat-angular.mjs.map +1 -1
  29. package/lib/channel.service.d.ts +7 -2
  30. package/lib/message-reactions/message-reactions.component.d.ts +19 -11
  31. package/lib/message-reactions.service.d.ts +14 -2
  32. package/lib/paginated-list/paginated-list.component.d.ts +42 -0
  33. package/lib/stream-chat.module.d.ts +7 -5
  34. package/lib/types.d.ts +11 -2
  35. package/lib/user-list/user-list.component.d.ts +30 -0
  36. package/package.json +2 -2
  37. package/public-api.d.ts +2 -0
  38. package/src/assets/styles/css/index.css +2 -2
  39. package/src/assets/styles/css/index.layout.css +1 -1
  40. package/src/assets/styles/scss/MessageActionsBox/MessageActionsBox-theme.scss +8 -0
  41. package/src/assets/styles/scss/MessageReactions/MessageReactionsSelector-theme.scss +6 -0
  42. package/src/assets/styles/scss/_base.scss +31 -0
  43. package/src/assets/version.ts +1 -1
@@ -1,6 +1,6 @@
1
1
  import { __awaiter } from 'tslib';
2
2
  import * as i0 from '@angular/core';
3
- import { Injectable, Component, Input, EventEmitter, Output, ViewChild, HostBinding, ChangeDetectionStrategy, InjectionToken, Directive, Inject, NgModule } from '@angular/core';
3
+ import { Injectable, Component, Input, EventEmitter, Output, ViewChild, HostBinding, TemplateRef, ContentChild, ChangeDetectionStrategy, InjectionToken, Directive, Inject, NgModule } from '@angular/core';
4
4
  import { BehaviorSubject, ReplaySubject, combineLatest, take as take$1, Subject, timer, merge, switchMap, distinctUntilChanged, pairwise, filter as filter$1, of, map as map$1 } from 'rxjs';
5
5
  import { StreamChat } from 'stream-chat';
6
6
  import { take, shareReplay, map, first, filter, tap, debounceTime, throttleTime } from 'rxjs/operators';
@@ -20,7 +20,7 @@ import transliterate from '@stream-io/transliterate';
20
20
  import * as i8$1 from 'angular-mentions';
21
21
  import { MentionModule } from 'angular-mentions';
22
22
 
23
- const version = '5.1.10';
23
+ const version = '5.2.0';
24
24
 
25
25
  /**
26
26
  * The `NotificationService` can be used to add or remove notifications. By default the [`NotificationList`](../components/NotificationListComponent.mdx) component displays the currently active notifications.
@@ -1461,6 +1461,7 @@ class ChannelService {
1461
1461
  }
1462
1462
  /**
1463
1463
  * Get the last 1200 reactions of a message in the current active channel. If you need to fetch more reactions please use the [following endpoint](https://getstream.io/chat/docs/javascript/send_reaction/?language=javascript#paginating-reactions).
1464
+ * @deprecated use [`messageReactionsService.queryReactions()`](https://getstream.io/chat/docs/sdk/angular/services/MessageReactionsService/#queryreactions) instead
1464
1465
  * @param messageId
1465
1466
  * @returns all reactions of a message
1466
1467
  */
@@ -1558,7 +1559,7 @@ class ChannelService {
1558
1559
  }
1559
1560
  messageReactionEventReceived(e) {
1560
1561
  this.ngZone.run(() => {
1561
- var _a, _b, _c, _d;
1562
+ var _a, _b, _c, _d, _e;
1562
1563
  const isThreadMessage = e.message && e.message.parent_id;
1563
1564
  let messages;
1564
1565
  (isThreadMessage
@@ -1575,6 +1576,7 @@ class ChannelService {
1575
1576
  message.reaction_scores = Object.assign({}, (_b = e.message) === null || _b === void 0 ? void 0 : _b.reaction_scores);
1576
1577
  message.latest_reactions = [...(((_c = e.message) === null || _c === void 0 ? void 0 : _c.latest_reactions) || [])];
1577
1578
  message.own_reactions = [...(((_d = e.message) === null || _d === void 0 ? void 0 : _d.own_reactions) || [])];
1579
+ message.reaction_groups = Object.assign({}, (_e = e.message) === null || _e === void 0 ? void 0 : _e.reaction_groups);
1578
1580
  messages[messageIndex] = Object.assign({}, message);
1579
1581
  isThreadMessage
1580
1582
  ? this.activeThreadMessagesSubject.next([...messages])
@@ -3381,7 +3383,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.4", ngImpor
3381
3383
  *
3382
3384
  */
3383
3385
  class MessageReactionsService {
3384
- constructor() {
3386
+ constructor(chatClientService, notificationService) {
3387
+ this.chatClientService = chatClientService;
3388
+ this.notificationService = notificationService;
3385
3389
  /**
3386
3390
  * The enabled [reactions](https://getstream.io/chat/docs/javascript/send_reaction/?language=javascript) and the associated emoji
3387
3391
  *
@@ -3407,15 +3411,39 @@ class MessageReactionsService {
3407
3411
  get reactions() {
3408
3412
  return this.reactions$.getValue();
3409
3413
  }
3414
+ /**
3415
+ * Query reactions of a specific message, more info in the [API documentation](https://getstream.io/chat/docs/javascript/send_reaction/?language=javascript#query-reactions)
3416
+ * @param messageId
3417
+ * @param type
3418
+ * @param next
3419
+ * @returns the reactions and the cursor for the next/prev pages
3420
+ */
3421
+ queryReactions(messageId, type, next) {
3422
+ return __awaiter(this, void 0, void 0, function* () {
3423
+ if (!this.chatClientService.chatClient) {
3424
+ throw new Error('Intialize the ChatClientService before querying reactions');
3425
+ }
3426
+ else {
3427
+ try {
3428
+ const response = yield this.chatClientService.chatClient.queryReactions(messageId, { type }, { created_at: -1 }, { next });
3429
+ return response;
3430
+ }
3431
+ catch (error) {
3432
+ this.notificationService.addTemporaryNotification('streamChat.Error loading reactions');
3433
+ throw error;
3434
+ }
3435
+ }
3436
+ });
3437
+ }
3410
3438
  }
3411
- MessageReactionsService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.4", ngImport: i0, type: MessageReactionsService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
3439
+ MessageReactionsService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.4", ngImport: i0, type: MessageReactionsService, deps: [{ token: ChatClientService }, { token: NotificationService }], target: i0.ɵɵFactoryTarget.Injectable });
3412
3440
  MessageReactionsService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.0.4", ngImport: i0, type: MessageReactionsService, providedIn: 'root' });
3413
3441
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.4", ngImport: i0, type: MessageReactionsService, decorators: [{
3414
3442
  type: Injectable,
3415
3443
  args: [{
3416
3444
  providedIn: 'root',
3417
3445
  }]
3418
- }], ctorParameters: function () { return []; } });
3446
+ }], ctorParameters: function () { return [{ type: ChatClientService }, { type: NotificationService }]; } });
3419
3447
 
3420
3448
  /**
3421
3449
  * The `MessageReactionsSelectorComponent` makes it possible for users to react to a message, the reaction options can be set using the [`MessageReactionsService`](../../services/MessageReactionsService). You can read more about [message reactions](https://getstream.io/chat/docs/javascript/send_reaction/?language=javascript) in the platform documentation.
@@ -3465,10 +3493,10 @@ class MessageReactionsSelectorComponent {
3465
3493
  }
3466
3494
  }
3467
3495
  MessageReactionsSelectorComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.4", ngImport: i0, type: MessageReactionsSelectorComponent, deps: [{ token: ChannelService }, { token: MessageReactionsService }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
3468
- MessageReactionsSelectorComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.0.4", type: MessageReactionsSelectorComponent, selector: "stream-message-reactions-selector", inputs: { ownReactions: "ownReactions", messageId: "messageId" }, ngImport: i0, template: "<div\n #selectorContainer\n data-testid=\"reaction-selector\"\n class=\"\n str-chat__reaction-selector\n str-chat-angular-v5__reaction-selector\n str-chat__message-reaction-selector\n \"\n>\n <ul\n class=\"str-chat__message-reactions-list str-chat__message-reactions-options\"\n >\n <li\n *ngFor=\"\n let reactionType of reactionOptions;\n trackBy: trackByMessageReaction\n \"\n class=\"\n str-chat__message-reactions-option\n str-chat__message-reactions-list-item\n str-chat__emoji\n \"\n data-testclass=\"emoji-option\"\n [attr.data-testid]=\"reactionType\"\n [class.str-chat__message-reactions-option-selected]=\"\n isOwnReaction(reactionType)\n \"\n (click)=\"react(reactionType)\"\n (keyup.enter)=\"react(reactionType)\"\n >\n <span\n class=\"\n emoji\n str-chat__emoji-selector-emoji-angular\n str-chat__message-reaction-emoji\n \"\n >\n {{ getEmojiByReaction(reactionType) }}\n </span>\n </li>\n </ul>\n</div>\n", dependencies: [{ kind: "directive", type: i4.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }] });
3496
+ MessageReactionsSelectorComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.0.4", type: MessageReactionsSelectorComponent, selector: "stream-message-reactions-selector", inputs: { ownReactions: "ownReactions", messageId: "messageId" }, ngImport: i0, template: "<div\n #selectorContainer\n data-testid=\"reaction-selector\"\n class=\"str-chat__reaction-selector str-chat-angular-v5__reaction-selector str-chat__message-reaction-selector\"\n>\n <ul\n class=\"str-chat__message-reactions-list str-chat__message-reactions-options\"\n >\n <li\n *ngFor=\"\n let reactionType of reactionOptions;\n trackBy: trackByMessageReaction\n \"\n class=\"str-chat__message-reactions-option str-chat__message-reactions-list-item str-chat__emoji\"\n data-testclass=\"emoji-option\"\n [attr.data-testid]=\"reactionType\"\n [class.str-chat__message-reactions-option-selected]=\"\n isOwnReaction(reactionType)\n \"\n (click)=\"react(reactionType)\"\n (keyup.enter)=\"react(reactionType)\"\n >\n <span\n class=\"emoji str-chat__emoji-selector-emoji-angular str-chat__message-reaction-emoji\"\n >\n {{ getEmojiByReaction(reactionType) }}\n </span>\n </li>\n </ul>\n</div>\n", dependencies: [{ kind: "directive", type: i4.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }] });
3469
3497
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.4", ngImport: i0, type: MessageReactionsSelectorComponent, decorators: [{
3470
3498
  type: Component,
3471
- args: [{ selector: 'stream-message-reactions-selector', template: "<div\n #selectorContainer\n data-testid=\"reaction-selector\"\n class=\"\n str-chat__reaction-selector\n str-chat-angular-v5__reaction-selector\n str-chat__message-reaction-selector\n \"\n>\n <ul\n class=\"str-chat__message-reactions-list str-chat__message-reactions-options\"\n >\n <li\n *ngFor=\"\n let reactionType of reactionOptions;\n trackBy: trackByMessageReaction\n \"\n class=\"\n str-chat__message-reactions-option\n str-chat__message-reactions-list-item\n str-chat__emoji\n \"\n data-testclass=\"emoji-option\"\n [attr.data-testid]=\"reactionType\"\n [class.str-chat__message-reactions-option-selected]=\"\n isOwnReaction(reactionType)\n \"\n (click)=\"react(reactionType)\"\n (keyup.enter)=\"react(reactionType)\"\n >\n <span\n class=\"\n emoji\n str-chat__emoji-selector-emoji-angular\n str-chat__message-reaction-emoji\n \"\n >\n {{ getEmojiByReaction(reactionType) }}\n </span>\n </li>\n </ul>\n</div>\n" }]
3499
+ args: [{ selector: 'stream-message-reactions-selector', template: "<div\n #selectorContainer\n data-testid=\"reaction-selector\"\n class=\"str-chat__reaction-selector str-chat-angular-v5__reaction-selector str-chat__message-reaction-selector\"\n>\n <ul\n class=\"str-chat__message-reactions-list str-chat__message-reactions-options\"\n >\n <li\n *ngFor=\"\n let reactionType of reactionOptions;\n trackBy: trackByMessageReaction\n \"\n class=\"str-chat__message-reactions-option str-chat__message-reactions-list-item str-chat__emoji\"\n data-testclass=\"emoji-option\"\n [attr.data-testid]=\"reactionType\"\n [class.str-chat__message-reactions-option-selected]=\"\n isOwnReaction(reactionType)\n \"\n (click)=\"react(reactionType)\"\n (keyup.enter)=\"react(reactionType)\"\n >\n <span\n class=\"emoji str-chat__emoji-selector-emoji-angular str-chat__message-reaction-emoji\"\n >\n {{ getEmojiByReaction(reactionType) }}\n </span>\n </li>\n </ul>\n</div>\n" }]
3472
3500
  }], ctorParameters: function () { return [{ type: ChannelService }, { type: MessageReactionsService }, { type: i0.ChangeDetectorRef }]; }, propDecorators: { ownReactions: [{
3473
3501
  type: Input
3474
3502
  }], messageId: [{
@@ -3579,10 +3607,10 @@ class MessageActionsBoxComponent {
3579
3607
  }
3580
3608
  }
3581
3609
  MessageActionsBoxComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.4", ngImport: i0, type: MessageActionsBoxComponent, deps: [{ token: CustomTemplatesService }, { token: MessageActionsService }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
3582
- MessageActionsBoxComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.0.4", type: MessageActionsBoxComponent, selector: "stream-message-actions-box", inputs: { isMine: "isMine", message: "message", messageTextHtmlElement: "messageTextHtmlElement", enabledActions: "enabledActions" }, usesOnChanges: true, ngImport: i0, template: "<div\n #actionBox\n data-testid=\"action-box\"\n class=\"\n str-chat__message-actions-box\n str-chat__message-actions-box-angular\n str-chat__message-actions-box--open\n \"\n>\n <ul class=\"str-chat__message-actions-list\">\n <ng-container\n *ngFor=\"let item of visibleMessageActionItems; trackBy: trackByActionName\"\n >\n <ng-container [ngSwitch]=\"item.actionName\">\n <ng-container *ngSwitchCase=\"'react'\">\n <ng-container\n *ngTemplateOutlet=\"\n (customTemplatesService.messageReactionsSelectorTemplate$\n | async) || defaultReactionSelector;\n context: getReactionSelectorTemplateContext()\n \"\n ></ng-container>\n </ng-container>\n <ng-container *ngSwitchDefault>\n <ng-container\n *ngTemplateOutlet=\"\n (customTemplatesService.messageActionsBoxItemTemplate$ | async) ||\n defaultMessageActionItem;\n context: getMessageActionTemplateContext(item)\n \"\n ></ng-container>\n </ng-container>\n </ng-container>\n </ng-container>\n </ul>\n</div>\n\n<ng-template\n #defaultMessageActionItem\n let-actionName=\"actionName\"\n let-actionHandler=\"actionHandler\"\n let-actionLabelOrTranslationKey=\"actionLabelOrTranslationKey\"\n let-actionHandlerExtraParams=\"actionHandlerExtraParams\"\n>\n <button\n class=\"str-chat__message-actions-list-item-button\"\n [attr.data-testid]=\"actionName + '-action'\"\n (click)=\"actionHandler(message, actionHandlerExtraParams)\"\n >\n <li class=\"str-chat__message-actions-list-item\">\n {{ getActionLabel(actionLabelOrTranslationKey) | translate }}\n </li>\n </button>\n</ng-template>\n\n<ng-template\n #defaultReactionSelector\n let-messageId=\"messageId\"\n let-ownReactions=\"ownReactions\"\n>\n <stream-message-reactions-selector\n [messageId]=\"message?.id\"\n [ownReactions]=\"message?.own_reactions || []\"\n ></stream-message-reactions-selector>\n</ng-template>\n", dependencies: [{ kind: "directive", type: i4.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i4.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i4.NgSwitch, selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { kind: "directive", type: i4.NgSwitchCase, selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }, { kind: "directive", type: i4.NgSwitchDefault, selector: "[ngSwitchDefault]" }, { kind: "component", type: MessageReactionsSelectorComponent, selector: "stream-message-reactions-selector", inputs: ["ownReactions", "messageId"] }, { kind: "pipe", type: i4.AsyncPipe, name: "async" }, { kind: "pipe", type: i10.TranslatePipe, name: "translate" }] });
3610
+ MessageActionsBoxComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.0.4", type: MessageActionsBoxComponent, selector: "stream-message-actions-box", inputs: { isMine: "isMine", message: "message", messageTextHtmlElement: "messageTextHtmlElement", enabledActions: "enabledActions" }, usesOnChanges: true, ngImport: i0, template: "<div\n #actionBox\n data-testid=\"action-box\"\n class=\"str-chat__message-actions-box str-chat__message-actions-box-angular str-chat__message-actions-box--open\"\n>\n <ul class=\"str-chat__message-actions-list\">\n <ng-container\n *ngFor=\"let item of visibleMessageActionItems; trackBy: trackByActionName\"\n >\n <ng-container [ngSwitch]=\"item.actionName\">\n <ng-container *ngSwitchCase=\"'react'\">\n <ng-container\n *ngTemplateOutlet=\"\n (customTemplatesService.messageReactionsSelectorTemplate$\n | async) || defaultReactionSelector;\n context: getReactionSelectorTemplateContext()\n \"\n ></ng-container>\n </ng-container>\n <ng-container *ngSwitchDefault>\n <ng-container\n *ngTemplateOutlet=\"\n (customTemplatesService.messageActionsBoxItemTemplate$ | async) ||\n defaultMessageActionItem;\n context: getMessageActionTemplateContext(item)\n \"\n ></ng-container>\n </ng-container>\n </ng-container>\n </ng-container>\n </ul>\n</div>\n\n<ng-template\n #defaultMessageActionItem\n let-actionName=\"actionName\"\n let-actionHandler=\"actionHandler\"\n let-actionLabelOrTranslationKey=\"actionLabelOrTranslationKey\"\n let-actionHandlerExtraParams=\"actionHandlerExtraParams\"\n>\n <button\n class=\"str-chat__message-actions-list-item-button\"\n [attr.data-testid]=\"actionName + '-action'\"\n (click)=\"actionHandler(message, actionHandlerExtraParams)\"\n >\n <li class=\"str-chat__message-actions-list-item\">\n {{ getActionLabel(actionLabelOrTranslationKey) | translate }}\n </li>\n </button>\n</ng-template>\n\n<ng-template\n #defaultReactionSelector\n let-messageId=\"messageId\"\n let-ownReactions=\"ownReactions\"\n>\n <stream-message-reactions-selector\n [messageId]=\"message?.id\"\n [ownReactions]=\"message?.own_reactions || []\"\n ></stream-message-reactions-selector>\n</ng-template>\n", dependencies: [{ kind: "directive", type: i4.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i4.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i4.NgSwitch, selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { kind: "directive", type: i4.NgSwitchCase, selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }, { kind: "directive", type: i4.NgSwitchDefault, selector: "[ngSwitchDefault]" }, { kind: "component", type: MessageReactionsSelectorComponent, selector: "stream-message-reactions-selector", inputs: ["ownReactions", "messageId"] }, { kind: "pipe", type: i4.AsyncPipe, name: "async" }, { kind: "pipe", type: i10.TranslatePipe, name: "translate" }] });
3583
3611
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.4", ngImport: i0, type: MessageActionsBoxComponent, decorators: [{
3584
3612
  type: Component,
3585
- args: [{ selector: 'stream-message-actions-box', template: "<div\n #actionBox\n data-testid=\"action-box\"\n class=\"\n str-chat__message-actions-box\n str-chat__message-actions-box-angular\n str-chat__message-actions-box--open\n \"\n>\n <ul class=\"str-chat__message-actions-list\">\n <ng-container\n *ngFor=\"let item of visibleMessageActionItems; trackBy: trackByActionName\"\n >\n <ng-container [ngSwitch]=\"item.actionName\">\n <ng-container *ngSwitchCase=\"'react'\">\n <ng-container\n *ngTemplateOutlet=\"\n (customTemplatesService.messageReactionsSelectorTemplate$\n | async) || defaultReactionSelector;\n context: getReactionSelectorTemplateContext()\n \"\n ></ng-container>\n </ng-container>\n <ng-container *ngSwitchDefault>\n <ng-container\n *ngTemplateOutlet=\"\n (customTemplatesService.messageActionsBoxItemTemplate$ | async) ||\n defaultMessageActionItem;\n context: getMessageActionTemplateContext(item)\n \"\n ></ng-container>\n </ng-container>\n </ng-container>\n </ng-container>\n </ul>\n</div>\n\n<ng-template\n #defaultMessageActionItem\n let-actionName=\"actionName\"\n let-actionHandler=\"actionHandler\"\n let-actionLabelOrTranslationKey=\"actionLabelOrTranslationKey\"\n let-actionHandlerExtraParams=\"actionHandlerExtraParams\"\n>\n <button\n class=\"str-chat__message-actions-list-item-button\"\n [attr.data-testid]=\"actionName + '-action'\"\n (click)=\"actionHandler(message, actionHandlerExtraParams)\"\n >\n <li class=\"str-chat__message-actions-list-item\">\n {{ getActionLabel(actionLabelOrTranslationKey) | translate }}\n </li>\n </button>\n</ng-template>\n\n<ng-template\n #defaultReactionSelector\n let-messageId=\"messageId\"\n let-ownReactions=\"ownReactions\"\n>\n <stream-message-reactions-selector\n [messageId]=\"message?.id\"\n [ownReactions]=\"message?.own_reactions || []\"\n ></stream-message-reactions-selector>\n</ng-template>\n" }]
3613
+ args: [{ selector: 'stream-message-actions-box', template: "<div\n #actionBox\n data-testid=\"action-box\"\n class=\"str-chat__message-actions-box str-chat__message-actions-box-angular str-chat__message-actions-box--open\"\n>\n <ul class=\"str-chat__message-actions-list\">\n <ng-container\n *ngFor=\"let item of visibleMessageActionItems; trackBy: trackByActionName\"\n >\n <ng-container [ngSwitch]=\"item.actionName\">\n <ng-container *ngSwitchCase=\"'react'\">\n <ng-container\n *ngTemplateOutlet=\"\n (customTemplatesService.messageReactionsSelectorTemplate$\n | async) || defaultReactionSelector;\n context: getReactionSelectorTemplateContext()\n \"\n ></ng-container>\n </ng-container>\n <ng-container *ngSwitchDefault>\n <ng-container\n *ngTemplateOutlet=\"\n (customTemplatesService.messageActionsBoxItemTemplate$ | async) ||\n defaultMessageActionItem;\n context: getMessageActionTemplateContext(item)\n \"\n ></ng-container>\n </ng-container>\n </ng-container>\n </ng-container>\n </ul>\n</div>\n\n<ng-template\n #defaultMessageActionItem\n let-actionName=\"actionName\"\n let-actionHandler=\"actionHandler\"\n let-actionLabelOrTranslationKey=\"actionLabelOrTranslationKey\"\n let-actionHandlerExtraParams=\"actionHandlerExtraParams\"\n>\n <button\n class=\"str-chat__message-actions-list-item-button\"\n [attr.data-testid]=\"actionName + '-action'\"\n (click)=\"actionHandler(message, actionHandlerExtraParams)\"\n >\n <li class=\"str-chat__message-actions-list-item\">\n {{ getActionLabel(actionLabelOrTranslationKey) | translate }}\n </li>\n </button>\n</ng-template>\n\n<ng-template\n #defaultReactionSelector\n let-messageId=\"messageId\"\n let-ownReactions=\"ownReactions\"\n>\n <stream-message-reactions-selector\n [messageId]=\"message?.id\"\n [ownReactions]=\"message?.own_reactions || []\"\n ></stream-message-reactions-selector>\n</ng-template>\n" }]
3586
3614
  }], ctorParameters: function () { return [{ type: CustomTemplatesService }, { type: MessageActionsService }, { type: i0.ChangeDetectorRef }]; }, propDecorators: { isMine: [{
3587
3615
  type: Input
3588
3616
  }], message: [{
@@ -3629,10 +3657,10 @@ class NotificationListComponent {
3629
3657
  }
3630
3658
  }
3631
3659
  NotificationListComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.4", ngImport: i0, type: NotificationListComponent, deps: [{ token: CustomTemplatesService }, { token: NotificationService }, { token: ThemeService }], target: i0.ɵɵFactoryTarget.Component });
3632
- NotificationListComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.0.4", type: NotificationListComponent, selector: "stream-notification-list", ngImport: i0, template: "<div\n data-testid=\"notification-list\"\n class=\"str-chat str-chat__theme-{{\n theme$ | async\n }} str-chat__list-notifications\"\n>\n <ng-container\n *ngFor=\"let notification of notifications$ | async; trackBy: trackById\"\n >\n <ng-template #notificationContent>\n <div\n *ngIf=\"notification.text !== undefined\"\n data-testclass=\"notification-content\"\n >\n {{ notification.text | translate: notification.translateParams }}\n </div>\n <ng-container *ngIf=\"notification.template !== undefined\">\n <ng-container\n *ngTemplateOutlet=\"\n notification.template;\n context: getNotificationContentContext(notification)\n \"\n ></ng-container>\n </ng-container>\n </ng-template>\n <ng-container\n *ngTemplateOutlet=\"\n (customTemplatesService.notificationTemplate$ | async) ||\n defaultNotification;\n context: { type: notification.type, content: notificationContent }\n \"\n ></ng-container>\n </ng-container>\n</div>\n\n<ng-template #defaultNotification let-type=\"type\" let-content=\"content\">\n <stream-notification [type]=\"type\" [content]=\"content\"></stream-notification>\n</ng-template>\n", dependencies: [{ kind: "directive", type: i4.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i4.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: NotificationComponent, selector: "stream-notification", inputs: ["type", "content"] }, { kind: "pipe", type: i4.AsyncPipe, name: "async" }, { kind: "pipe", type: i10.TranslatePipe, name: "translate" }] });
3660
+ NotificationListComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.0.4", type: NotificationListComponent, selector: "stream-notification-list", ngImport: i0, template: "<div\n data-testid=\"notification-list\"\n class=\"str-chat str-chat__theme-{{\n theme$ | async\n }} str-chat__list-notifications\"\n>\n <ng-container\n *ngFor=\"let notification of notifications$ | async; trackBy: trackById\"\n >\n <ng-template #notificationContent>\n <div\n *ngIf=\"notification.text !== undefined\"\n data-testclass=\"notification-content\"\n >\n {{ notification.text | translate : notification.translateParams }}\n </div>\n <ng-container *ngIf=\"notification.template !== undefined\">\n <ng-container\n *ngTemplateOutlet=\"\n notification.template;\n context: getNotificationContentContext(notification)\n \"\n ></ng-container>\n </ng-container>\n </ng-template>\n <ng-container\n *ngTemplateOutlet=\"\n (customTemplatesService.notificationTemplate$ | async) ||\n defaultNotification;\n context: { type: notification.type, content: notificationContent }\n \"\n ></ng-container>\n </ng-container>\n</div>\n\n<ng-template #defaultNotification let-type=\"type\" let-content=\"content\">\n <stream-notification [type]=\"type\" [content]=\"content\"></stream-notification>\n</ng-template>\n", dependencies: [{ kind: "directive", type: i4.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i4.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: NotificationComponent, selector: "stream-notification", inputs: ["type", "content"] }, { kind: "pipe", type: i4.AsyncPipe, name: "async" }, { kind: "pipe", type: i10.TranslatePipe, name: "translate" }] });
3633
3661
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.4", ngImport: i0, type: NotificationListComponent, decorators: [{
3634
3662
  type: Component,
3635
- args: [{ selector: 'stream-notification-list', template: "<div\n data-testid=\"notification-list\"\n class=\"str-chat str-chat__theme-{{\n theme$ | async\n }} str-chat__list-notifications\"\n>\n <ng-container\n *ngFor=\"let notification of notifications$ | async; trackBy: trackById\"\n >\n <ng-template #notificationContent>\n <div\n *ngIf=\"notification.text !== undefined\"\n data-testclass=\"notification-content\"\n >\n {{ notification.text | translate: notification.translateParams }}\n </div>\n <ng-container *ngIf=\"notification.template !== undefined\">\n <ng-container\n *ngTemplateOutlet=\"\n notification.template;\n context: getNotificationContentContext(notification)\n \"\n ></ng-container>\n </ng-container>\n </ng-template>\n <ng-container\n *ngTemplateOutlet=\"\n (customTemplatesService.notificationTemplate$ | async) ||\n defaultNotification;\n context: { type: notification.type, content: notificationContent }\n \"\n ></ng-container>\n </ng-container>\n</div>\n\n<ng-template #defaultNotification let-type=\"type\" let-content=\"content\">\n <stream-notification [type]=\"type\" [content]=\"content\"></stream-notification>\n</ng-template>\n" }]
3663
+ args: [{ selector: 'stream-notification-list', template: "<div\n data-testid=\"notification-list\"\n class=\"str-chat str-chat__theme-{{\n theme$ | async\n }} str-chat__list-notifications\"\n>\n <ng-container\n *ngFor=\"let notification of notifications$ | async; trackBy: trackById\"\n >\n <ng-template #notificationContent>\n <div\n *ngIf=\"notification.text !== undefined\"\n data-testclass=\"notification-content\"\n >\n {{ notification.text | translate : notification.translateParams }}\n </div>\n <ng-container *ngIf=\"notification.template !== undefined\">\n <ng-container\n *ngTemplateOutlet=\"\n notification.template;\n context: getNotificationContentContext(notification)\n \"\n ></ng-container>\n </ng-container>\n </ng-template>\n <ng-container\n *ngTemplateOutlet=\"\n (customTemplatesService.notificationTemplate$ | async) ||\n defaultNotification;\n context: { type: notification.type, content: notificationContent }\n \"\n ></ng-container>\n </ng-container>\n</div>\n\n<ng-template #defaultNotification let-type=\"type\" let-content=\"content\">\n <stream-notification [type]=\"type\" [content]=\"content\"></stream-notification>\n</ng-template>\n" }]
3636
3664
  }], ctorParameters: function () { return [{ type: CustomTemplatesService }, { type: NotificationService }, { type: ThemeService }]; } });
3637
3665
 
3638
3666
  /**
@@ -3887,10 +3915,10 @@ class ChannelHeaderComponent {
3887
3915
  }
3888
3916
  }
3889
3917
  ChannelHeaderComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.4", ngImport: i0, type: ChannelHeaderComponent, deps: [{ token: ChannelService }, { token: CustomTemplatesService }, { token: i0.ChangeDetectorRef }, { token: ChatClientService }], target: i0.ɵɵFactoryTarget.Component });
3890
- ChannelHeaderComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.0.4", type: ChannelHeaderComponent, selector: "stream-channel-header", ngImport: i0, template: "<div class=\"str-chat__header-livestream str-chat__channel-header\">\n <ng-content></ng-content>\n <stream-avatar-placeholder\n type=\"channel\"\n location=\"channel-header\"\n imageUrl=\"{{ activeChannel?.data?.image }}\"\n name=\"{{ avatarName }}\"\n [channel]=\"activeChannel\"\n ></stream-avatar-placeholder>\n <div class=\"str-chat__header-livestream-left str-chat__channel-header-end\">\n <p\n data-testid=\"name\"\n class=\"\n str-chat__header-livestream-left--title str-chat__channel-header-title\n \"\n >\n {{ displayText }}\n </p>\n <ng-container\n *ngTemplateOutlet=\"\n channelHeaderInfoTemplate || defaultChannelInfo;\n context: getChannelInfoContext()\n \"\n ></ng-container>\n <ng-template #defaultChannelInfo>\n <p\n data-testid=\"info\"\n class=\"\n str-chat__header-livestream-left--members\n str-chat__channel-header-info\n \"\n >\n {{'streamChat.{{ memberCount }} members' | translate:memberCountParam}}\n {{canReceiveConnectEvents ? ('streamChat.{{ watcherCount }} online' |\n translate:watcherCountParam) : ''}}\n </p>\n </ng-template>\n </div>\n <ng-container *ngIf=\"channelActionsTemplate\">\n <ng-container\n *ngTemplateOutlet=\"\n channelActionsTemplate;\n context: getChannelActionsContext()\n \"\n ></ng-container>\n </ng-container>\n</div>\n", dependencies: [{ kind: "directive", type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i4.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: AvatarPlaceholderComponent, selector: "stream-avatar-placeholder", inputs: ["name", "imageUrl", "location", "channel", "user", "type", "initialsType", "showOnlineIndicator"] }, { kind: "pipe", type: i10.TranslatePipe, name: "translate" }] });
3918
+ ChannelHeaderComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.0.4", type: ChannelHeaderComponent, selector: "stream-channel-header", ngImport: i0, template: "<div class=\"str-chat__header-livestream str-chat__channel-header\">\n <ng-content></ng-content>\n <stream-avatar-placeholder\n type=\"channel\"\n location=\"channel-header\"\n imageUrl=\"{{ activeChannel?.data?.image }}\"\n name=\"{{ avatarName }}\"\n [channel]=\"activeChannel\"\n ></stream-avatar-placeholder>\n <div class=\"str-chat__header-livestream-left str-chat__channel-header-end\">\n <p\n data-testid=\"name\"\n class=\"str-chat__header-livestream-left--title str-chat__channel-header-title\"\n >\n {{ displayText }}\n </p>\n <ng-container\n *ngTemplateOutlet=\"\n channelHeaderInfoTemplate || defaultChannelInfo;\n context: getChannelInfoContext()\n \"\n ></ng-container>\n <ng-template #defaultChannelInfo>\n <p\n data-testid=\"info\"\n class=\"str-chat__header-livestream-left--members str-chat__channel-header-info\"\n >\n {{'streamChat.{{ memberCount }} members' | translate:memberCountParam}}\n {{canReceiveConnectEvents ? ('streamChat.{{ watcherCount }} online' |\n translate:watcherCountParam) : ''}}\n </p>\n </ng-template>\n </div>\n <ng-container *ngIf=\"channelActionsTemplate\">\n <ng-container\n *ngTemplateOutlet=\"\n channelActionsTemplate;\n context: getChannelActionsContext()\n \"\n ></ng-container>\n </ng-container>\n</div>\n", dependencies: [{ kind: "directive", type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i4.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: AvatarPlaceholderComponent, selector: "stream-avatar-placeholder", inputs: ["name", "imageUrl", "location", "channel", "user", "type", "initialsType", "showOnlineIndicator"] }, { kind: "pipe", type: i10.TranslatePipe, name: "translate" }] });
3891
3919
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.4", ngImport: i0, type: ChannelHeaderComponent, decorators: [{
3892
3920
  type: Component,
3893
- args: [{ selector: 'stream-channel-header', template: "<div class=\"str-chat__header-livestream str-chat__channel-header\">\n <ng-content></ng-content>\n <stream-avatar-placeholder\n type=\"channel\"\n location=\"channel-header\"\n imageUrl=\"{{ activeChannel?.data?.image }}\"\n name=\"{{ avatarName }}\"\n [channel]=\"activeChannel\"\n ></stream-avatar-placeholder>\n <div class=\"str-chat__header-livestream-left str-chat__channel-header-end\">\n <p\n data-testid=\"name\"\n class=\"\n str-chat__header-livestream-left--title str-chat__channel-header-title\n \"\n >\n {{ displayText }}\n </p>\n <ng-container\n *ngTemplateOutlet=\"\n channelHeaderInfoTemplate || defaultChannelInfo;\n context: getChannelInfoContext()\n \"\n ></ng-container>\n <ng-template #defaultChannelInfo>\n <p\n data-testid=\"info\"\n class=\"\n str-chat__header-livestream-left--members\n str-chat__channel-header-info\n \"\n >\n {{'streamChat.{{ memberCount }} members' | translate:memberCountParam}}\n {{canReceiveConnectEvents ? ('streamChat.{{ watcherCount }} online' |\n translate:watcherCountParam) : ''}}\n </p>\n </ng-template>\n </div>\n <ng-container *ngIf=\"channelActionsTemplate\">\n <ng-container\n *ngTemplateOutlet=\"\n channelActionsTemplate;\n context: getChannelActionsContext()\n \"\n ></ng-container>\n </ng-container>\n</div>\n" }]
3921
+ args: [{ selector: 'stream-channel-header', template: "<div class=\"str-chat__header-livestream str-chat__channel-header\">\n <ng-content></ng-content>\n <stream-avatar-placeholder\n type=\"channel\"\n location=\"channel-header\"\n imageUrl=\"{{ activeChannel?.data?.image }}\"\n name=\"{{ avatarName }}\"\n [channel]=\"activeChannel\"\n ></stream-avatar-placeholder>\n <div class=\"str-chat__header-livestream-left str-chat__channel-header-end\">\n <p\n data-testid=\"name\"\n class=\"str-chat__header-livestream-left--title str-chat__channel-header-title\"\n >\n {{ displayText }}\n </p>\n <ng-container\n *ngTemplateOutlet=\"\n channelHeaderInfoTemplate || defaultChannelInfo;\n context: getChannelInfoContext()\n \"\n ></ng-container>\n <ng-template #defaultChannelInfo>\n <p\n data-testid=\"info\"\n class=\"str-chat__header-livestream-left--members str-chat__channel-header-info\"\n >\n {{'streamChat.{{ memberCount }} members' | translate:memberCountParam}}\n {{canReceiveConnectEvents ? ('streamChat.{{ watcherCount }} online' |\n translate:watcherCountParam) : ''}}\n </p>\n </ng-template>\n </div>\n <ng-container *ngIf=\"channelActionsTemplate\">\n <ng-container\n *ngTemplateOutlet=\"\n channelActionsTemplate;\n context: getChannelActionsContext()\n \"\n ></ng-container>\n </ng-container>\n</div>\n" }]
3894
3922
  }], ctorParameters: function () { return [{ type: ChannelService }, { type: CustomTemplatesService }, { type: i0.ChangeDetectorRef }, { type: ChatClientService }]; } });
3895
3923
 
3896
3924
  const isOnSeparateDate = (date1, date2) => {
@@ -4139,10 +4167,10 @@ class ChannelPreviewComponent {
4139
4167
  }
4140
4168
  }
4141
4169
  ChannelPreviewComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.4", ngImport: i0, type: ChannelPreviewComponent, deps: [{ token: ChannelService }, { token: i0.NgZone }, { token: ChatClientService }, { token: MessageService }, { token: CustomTemplatesService }, { token: DateParserService }], target: i0.ɵɵFactoryTarget.Component });
4142
- ChannelPreviewComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.0.4", type: ChannelPreviewComponent, selector: "stream-channel-preview", inputs: { channel: "channel" }, ngImport: i0, template: "<button\n class=\"str-chat__channel-preview-messenger str-chat__channel-preview\"\n data-testid=\"channel-preview-container\"\n [class.str-chat__channel-preview-messenger--active]=\"isActive\"\n [class.str-chat__channel-preview--active]=\"isActive\"\n [class.str-chat__channel-preview-messenger--unread]=\"isUnread\"\n (click)=\"setAsActiveChannel()\"\n>\n <div class=\"str-chat__channel-preview-messenger--left\">\n <stream-avatar-placeholder\n type=\"channel\"\n location=\"channel-preview\"\n name=\"{{ avatarName }}\"\n imageUrl=\"{{ avatarImage }}\"\n [channel]=\"channel\"\n ></stream-avatar-placeholder>\n </div>\n <div\n class=\"\n str-chat__channel-preview-messenger--right str-chat__channel-preview-end\n \"\n >\n <ng-container\n *ngTemplateOutlet=\"\n (customTemplatesService.channelPreviewInfoTemplate$ | async) ||\n defaultChannelInfo;\n context: {\n channelDisplayTitle: title,\n channel: channel,\n unreadCount: unreadCount,\n latestMessageText: latestMessageText,\n latestMessageStatus: latestMessageStatus,\n latestMessageTime: latestMessageTime,\n latestMessage: latestMessage\n }\n \"\n ></ng-container>\n <ng-template\n #defaultChannelInfo\n let-channelDisplayTitle=\"channelDisplayTitle\"\n let-unreadCount=\"unreadCount\"\n let-latestMessageText=\"latestMessageText\"\n let-latestMessageStatus=\"latestMessageStatus\"\n let-latestMessageTime=\"latestMessageTime\"\n >\n <div class=\"str-chat__channel-preview-end-first-row\">\n <div class=\"str-chat__channel-preview-messenger--name\">\n <span data-testid=\"channel-preview-title\">{{\n channelDisplayTitle\n }}</span>\n </div>\n <div\n *ngIf=\"unreadCount\"\n data-testid=\"unread-badge\"\n class=\"str-chat__channel-preview-unread-badge\"\n >\n {{ unreadCount }}\n </div>\n </div>\n <div class=\"str-chat__channel-preview-end-second-row\">\n <div\n data-testid=\"latest-message\"\n class=\"str-chat__channel-preview-messenger--last-message\"\n >\n <ng-container *ngIf=\"displayAs === 'text'; else asHTML\">\n {{ latestMessageText | translate }}\n </ng-container>\n <ng-template #asHTML>\n <span\n data-testid=\"html-content\"\n [innerHTML]=\"latestMessageText | translate\"\n ></span>\n </ng-template>\n </div>\n <div\n *ngIf=\"latestMessageStatus\"\n data-testid=\"latest-message-status\"\n class=\"str-chat__channel-preview-messenger--status str-chat__channel-preview-messenger--status-{{\n latestMessageStatus\n }}\"\n >\n <stream-icon-placeholder\n [icon]=\"latestMessageStatus === 'delivered' ? 'delivered' : 'read'\"\n ></stream-icon-placeholder>\n </div>\n <div\n *ngIf=\"latestMessageTime\"\n data-testid=\"latest-message-time\"\n class=\"str-chat__channel-preview-messenger--time\"\n >\n {{ latestMessageTime }}\n </div>\n </div>\n </ng-template>\n </div>\n</button>\n", dependencies: [{ kind: "directive", type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i4.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: AvatarPlaceholderComponent, selector: "stream-avatar-placeholder", inputs: ["name", "imageUrl", "location", "channel", "user", "type", "initialsType", "showOnlineIndicator"] }, { kind: "component", type: IconPlaceholderComponent, selector: "stream-icon-placeholder", inputs: ["icon"] }, { kind: "pipe", type: i4.AsyncPipe, name: "async" }, { kind: "pipe", type: i10.TranslatePipe, name: "translate" }] });
4170
+ ChannelPreviewComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.0.4", type: ChannelPreviewComponent, selector: "stream-channel-preview", inputs: { channel: "channel" }, ngImport: i0, template: "<button\n class=\"str-chat__channel-preview-messenger str-chat__channel-preview\"\n data-testid=\"channel-preview-container\"\n [class.str-chat__channel-preview-messenger--active]=\"isActive\"\n [class.str-chat__channel-preview--active]=\"isActive\"\n [class.str-chat__channel-preview-messenger--unread]=\"isUnread\"\n (click)=\"setAsActiveChannel()\"\n>\n <div class=\"str-chat__channel-preview-messenger--left\">\n <stream-avatar-placeholder\n type=\"channel\"\n location=\"channel-preview\"\n name=\"{{ avatarName }}\"\n imageUrl=\"{{ avatarImage }}\"\n [channel]=\"channel\"\n ></stream-avatar-placeholder>\n </div>\n <div\n class=\"str-chat__channel-preview-messenger--right str-chat__channel-preview-end\"\n >\n <ng-container\n *ngTemplateOutlet=\"\n (customTemplatesService.channelPreviewInfoTemplate$ | async) ||\n defaultChannelInfo;\n context: {\n channelDisplayTitle: title,\n channel: channel,\n unreadCount: unreadCount,\n latestMessageText: latestMessageText,\n latestMessageStatus: latestMessageStatus,\n latestMessageTime: latestMessageTime,\n latestMessage: latestMessage\n }\n \"\n ></ng-container>\n <ng-template\n #defaultChannelInfo\n let-channelDisplayTitle=\"channelDisplayTitle\"\n let-unreadCount=\"unreadCount\"\n let-latestMessageText=\"latestMessageText\"\n let-latestMessageStatus=\"latestMessageStatus\"\n let-latestMessageTime=\"latestMessageTime\"\n >\n <div class=\"str-chat__channel-preview-end-first-row\">\n <div class=\"str-chat__channel-preview-messenger--name\">\n <span data-testid=\"channel-preview-title\">{{\n channelDisplayTitle\n }}</span>\n </div>\n <div\n *ngIf=\"unreadCount\"\n data-testid=\"unread-badge\"\n class=\"str-chat__channel-preview-unread-badge\"\n >\n {{ unreadCount }}\n </div>\n </div>\n <div class=\"str-chat__channel-preview-end-second-row\">\n <div\n data-testid=\"latest-message\"\n class=\"str-chat__channel-preview-messenger--last-message\"\n >\n <ng-container *ngIf=\"displayAs === 'text'; else asHTML\">\n {{ latestMessageText | translate }}\n </ng-container>\n <ng-template #asHTML>\n <span\n data-testid=\"html-content\"\n [innerHTML]=\"latestMessageText | translate\"\n ></span>\n </ng-template>\n </div>\n <div\n *ngIf=\"latestMessageStatus\"\n data-testid=\"latest-message-status\"\n class=\"str-chat__channel-preview-messenger--status str-chat__channel-preview-messenger--status-{{\n latestMessageStatus\n }}\"\n >\n <stream-icon-placeholder\n [icon]=\"latestMessageStatus === 'delivered' ? 'delivered' : 'read'\"\n ></stream-icon-placeholder>\n </div>\n <div\n *ngIf=\"latestMessageTime\"\n data-testid=\"latest-message-time\"\n class=\"str-chat__channel-preview-messenger--time\"\n >\n {{ latestMessageTime }}\n </div>\n </div>\n </ng-template>\n </div>\n</button>\n", dependencies: [{ kind: "directive", type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i4.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: AvatarPlaceholderComponent, selector: "stream-avatar-placeholder", inputs: ["name", "imageUrl", "location", "channel", "user", "type", "initialsType", "showOnlineIndicator"] }, { kind: "component", type: IconPlaceholderComponent, selector: "stream-icon-placeholder", inputs: ["icon"] }, { kind: "pipe", type: i4.AsyncPipe, name: "async" }, { kind: "pipe", type: i10.TranslatePipe, name: "translate" }] });
4143
4171
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.4", ngImport: i0, type: ChannelPreviewComponent, decorators: [{
4144
4172
  type: Component,
4145
- args: [{ selector: 'stream-channel-preview', template: "<button\n class=\"str-chat__channel-preview-messenger str-chat__channel-preview\"\n data-testid=\"channel-preview-container\"\n [class.str-chat__channel-preview-messenger--active]=\"isActive\"\n [class.str-chat__channel-preview--active]=\"isActive\"\n [class.str-chat__channel-preview-messenger--unread]=\"isUnread\"\n (click)=\"setAsActiveChannel()\"\n>\n <div class=\"str-chat__channel-preview-messenger--left\">\n <stream-avatar-placeholder\n type=\"channel\"\n location=\"channel-preview\"\n name=\"{{ avatarName }}\"\n imageUrl=\"{{ avatarImage }}\"\n [channel]=\"channel\"\n ></stream-avatar-placeholder>\n </div>\n <div\n class=\"\n str-chat__channel-preview-messenger--right str-chat__channel-preview-end\n \"\n >\n <ng-container\n *ngTemplateOutlet=\"\n (customTemplatesService.channelPreviewInfoTemplate$ | async) ||\n defaultChannelInfo;\n context: {\n channelDisplayTitle: title,\n channel: channel,\n unreadCount: unreadCount,\n latestMessageText: latestMessageText,\n latestMessageStatus: latestMessageStatus,\n latestMessageTime: latestMessageTime,\n latestMessage: latestMessage\n }\n \"\n ></ng-container>\n <ng-template\n #defaultChannelInfo\n let-channelDisplayTitle=\"channelDisplayTitle\"\n let-unreadCount=\"unreadCount\"\n let-latestMessageText=\"latestMessageText\"\n let-latestMessageStatus=\"latestMessageStatus\"\n let-latestMessageTime=\"latestMessageTime\"\n >\n <div class=\"str-chat__channel-preview-end-first-row\">\n <div class=\"str-chat__channel-preview-messenger--name\">\n <span data-testid=\"channel-preview-title\">{{\n channelDisplayTitle\n }}</span>\n </div>\n <div\n *ngIf=\"unreadCount\"\n data-testid=\"unread-badge\"\n class=\"str-chat__channel-preview-unread-badge\"\n >\n {{ unreadCount }}\n </div>\n </div>\n <div class=\"str-chat__channel-preview-end-second-row\">\n <div\n data-testid=\"latest-message\"\n class=\"str-chat__channel-preview-messenger--last-message\"\n >\n <ng-container *ngIf=\"displayAs === 'text'; else asHTML\">\n {{ latestMessageText | translate }}\n </ng-container>\n <ng-template #asHTML>\n <span\n data-testid=\"html-content\"\n [innerHTML]=\"latestMessageText | translate\"\n ></span>\n </ng-template>\n </div>\n <div\n *ngIf=\"latestMessageStatus\"\n data-testid=\"latest-message-status\"\n class=\"str-chat__channel-preview-messenger--status str-chat__channel-preview-messenger--status-{{\n latestMessageStatus\n }}\"\n >\n <stream-icon-placeholder\n [icon]=\"latestMessageStatus === 'delivered' ? 'delivered' : 'read'\"\n ></stream-icon-placeholder>\n </div>\n <div\n *ngIf=\"latestMessageTime\"\n data-testid=\"latest-message-time\"\n class=\"str-chat__channel-preview-messenger--time\"\n >\n {{ latestMessageTime }}\n </div>\n </div>\n </ng-template>\n </div>\n</button>\n" }]
4173
+ args: [{ selector: 'stream-channel-preview', template: "<button\n class=\"str-chat__channel-preview-messenger str-chat__channel-preview\"\n data-testid=\"channel-preview-container\"\n [class.str-chat__channel-preview-messenger--active]=\"isActive\"\n [class.str-chat__channel-preview--active]=\"isActive\"\n [class.str-chat__channel-preview-messenger--unread]=\"isUnread\"\n (click)=\"setAsActiveChannel()\"\n>\n <div class=\"str-chat__channel-preview-messenger--left\">\n <stream-avatar-placeholder\n type=\"channel\"\n location=\"channel-preview\"\n name=\"{{ avatarName }}\"\n imageUrl=\"{{ avatarImage }}\"\n [channel]=\"channel\"\n ></stream-avatar-placeholder>\n </div>\n <div\n class=\"str-chat__channel-preview-messenger--right str-chat__channel-preview-end\"\n >\n <ng-container\n *ngTemplateOutlet=\"\n (customTemplatesService.channelPreviewInfoTemplate$ | async) ||\n defaultChannelInfo;\n context: {\n channelDisplayTitle: title,\n channel: channel,\n unreadCount: unreadCount,\n latestMessageText: latestMessageText,\n latestMessageStatus: latestMessageStatus,\n latestMessageTime: latestMessageTime,\n latestMessage: latestMessage\n }\n \"\n ></ng-container>\n <ng-template\n #defaultChannelInfo\n let-channelDisplayTitle=\"channelDisplayTitle\"\n let-unreadCount=\"unreadCount\"\n let-latestMessageText=\"latestMessageText\"\n let-latestMessageStatus=\"latestMessageStatus\"\n let-latestMessageTime=\"latestMessageTime\"\n >\n <div class=\"str-chat__channel-preview-end-first-row\">\n <div class=\"str-chat__channel-preview-messenger--name\">\n <span data-testid=\"channel-preview-title\">{{\n channelDisplayTitle\n }}</span>\n </div>\n <div\n *ngIf=\"unreadCount\"\n data-testid=\"unread-badge\"\n class=\"str-chat__channel-preview-unread-badge\"\n >\n {{ unreadCount }}\n </div>\n </div>\n <div class=\"str-chat__channel-preview-end-second-row\">\n <div\n data-testid=\"latest-message\"\n class=\"str-chat__channel-preview-messenger--last-message\"\n >\n <ng-container *ngIf=\"displayAs === 'text'; else asHTML\">\n {{ latestMessageText | translate }}\n </ng-container>\n <ng-template #asHTML>\n <span\n data-testid=\"html-content\"\n [innerHTML]=\"latestMessageText | translate\"\n ></span>\n </ng-template>\n </div>\n <div\n *ngIf=\"latestMessageStatus\"\n data-testid=\"latest-message-status\"\n class=\"str-chat__channel-preview-messenger--status str-chat__channel-preview-messenger--status-{{\n latestMessageStatus\n }}\"\n >\n <stream-icon-placeholder\n [icon]=\"latestMessageStatus === 'delivered' ? 'delivered' : 'read'\"\n ></stream-icon-placeholder>\n </div>\n <div\n *ngIf=\"latestMessageTime\"\n data-testid=\"latest-message-time\"\n class=\"str-chat__channel-preview-messenger--time\"\n >\n {{ latestMessageTime }}\n </div>\n </div>\n </ng-template>\n </div>\n</button>\n" }]
4146
4174
  }], ctorParameters: function () { return [{ type: ChannelService }, { type: i0.NgZone }, { type: ChatClientService }, { type: MessageService }, { type: CustomTemplatesService }, { type: DateParserService }]; }, propDecorators: { channel: [{
4147
4175
  type: Input
4148
4176
  }] } });
@@ -4179,10 +4207,10 @@ class ChannelListComponent {
4179
4207
  }
4180
4208
  }
4181
4209
  ChannelListComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.4", ngImport: i0, type: ChannelListComponent, deps: [{ token: ChannelService }, { token: CustomTemplatesService }, { token: ThemeService }], target: i0.ɵɵFactoryTarget.Component });
4182
- ChannelListComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.0.4", type: ChannelListComponent, selector: "stream-channel-list", viewQueries: [{ propertyName: "container", first: true, predicate: ["container"], descendants: true }], ngImport: i0, template: "<div\n #container\n data-testid=\"channel-list-container\"\n class=\"str-chat str-chat__channel-list str-chat-channel-list messaging str-chat__theme-{{\n theme$ | async\n }}\"\n>\n <div\n *ngIf=\"\n (isError$ | async) === false && (isInitializing$ | async) === false;\n else statusIndicator\n \"\n class=\"str-chat__channel-list-messenger\"\n >\n <div class=\"str-chat__channel-list-messenger__main\">\n <ng-content select=\"[channel-list-top]\"></ng-content>\n <div\n *ngIf=\"!(channels$ | async)?.length\"\n class=\"str-chat__channel-list-empty\"\n >\n <stream-icon icon=\"chat-bubble\"></stream-icon>\n <p data-testid=\"empty-channel-list-indicator\">\n {{ \"streamChat.You have no channels currently\" | translate }}\n </p>\n </div>\n <p\n *ngIf=\"!(channels$ | async)?.length\"\n class=\"str-chat__channel-list-empty-v1\"\n data-testid=\"empty-channel-list-indicator\"\n >\n {{ \"streamChat.You have no channels currently\" | translate }}\n </p>\n <ng-container\n *ngFor=\"let channel of channels$ | async; trackBy: trackByChannelId\"\n >\n <ng-template #defaultTemplate let-channelInput=\"channel\">\n <stream-channel-preview\n data-testclass=\"channel-preview\"\n [channel]=\"channelInput\"\n ></stream-channel-preview>\n </ng-template>\n <div>\n <ng-container\n *ngTemplateOutlet=\"\n customChannelPreviewTemplate || defaultTemplate;\n context: { channel: channel }\n \"\n ></ng-container>\n </div>\n </ng-container>\n <div\n *ngIf=\"hasMoreChannels$ | async\"\n class=\"str-chat__load-more-button\"\n data-testid=\"load-more\"\n (click)=\"loadMoreChannels()\"\n (keyup.enter)=\"loadMoreChannels()\"\n >\n <button\n class=\"str-chat__load-more-button__button str-chat__cta-button\"\n data-testid=\"load-more-button\"\n [disabled]=\"isLoadingMoreChannels\"\n >\n <span *ngIf=\"!isLoadingMoreChannels; else loadingIndicator\">{{\n \"Load more\" | translate\n }}</span>\n <ng-template #loadingIndicator\n ><stream-loading-indicator-placeholder></stream-loading-indicator-placeholder\n ></ng-template>\n </button>\n </div>\n <ng-content select=\"[channel-list-bottom]\"></ng-content>\n </div>\n </div>\n</div>\n\n<ng-template #statusIndicator>\n <ng-container *ngIf=\"isError$ | async\">\n <ng-container *ngTemplateOutlet=\"chatDown\"></ng-container>\n </ng-container>\n <ng-container *ngIf=\"isInitializing$ | async\">\n <ng-container *ngTemplateOutlet=\"loadingChannels\"></ng-container>\n </ng-container>\n</ng-template>\n\n<ng-template #chatDown>\n <div data-testid=\"chatdown-container\" class=\"str-chat__down\">\n <ng-container *ngTemplateOutlet=\"loadingChannels\"></ng-container>\n </div>\n</ng-template>\n\n<ng-template #loadingChannels>\n <div data-testid=\"loading-indicator\" class=\"str-chat__loading-channels\">\n <ng-container *ngTemplateOutlet=\"loadingChannel\"></ng-container>\n <ng-container *ngTemplateOutlet=\"loadingChannel\"></ng-container>\n <ng-container *ngTemplateOutlet=\"loadingChannel\"></ng-container>\n </div>\n</ng-template>\n\n<ng-template #loadingChannel>\n <div\n class=\"str-chat__loading-channels-item str-chat__channel-preview-loading\"\n >\n <div class=\"str-chat__loading-channels-avatar\"></div>\n <div\n class=\"\n str-chat__loading-channels-meta str-chat__channel-preview-end-loading\n \"\n >\n <div class=\"str-chat__loading-channels-username\"></div>\n <div class=\"str-chat__loading-channels-status\"></div>\n </div>\n </div>\n</ng-template>\n", dependencies: [{ kind: "directive", type: i4.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i4.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: ChannelPreviewComponent, selector: "stream-channel-preview", inputs: ["channel"] }, { kind: "component", type: IconComponent, selector: "stream-icon", inputs: ["icon"] }, { kind: "component", type: LoadingIndicatorPlaceholderComponent, selector: "stream-loading-indicator-placeholder" }, { kind: "pipe", type: i4.AsyncPipe, name: "async" }, { kind: "pipe", type: i10.TranslatePipe, name: "translate" }] });
4210
+ ChannelListComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.0.4", type: ChannelListComponent, selector: "stream-channel-list", viewQueries: [{ propertyName: "container", first: true, predicate: ["container"], descendants: true }], ngImport: i0, template: "<div\n #container\n data-testid=\"channel-list-container\"\n class=\"str-chat str-chat__channel-list str-chat-channel-list messaging str-chat__theme-{{\n theme$ | async\n }}\"\n>\n <div\n *ngIf=\"\n (isError$ | async) === false && (isInitializing$ | async) === false;\n else statusIndicator\n \"\n class=\"str-chat__channel-list-messenger\"\n >\n <div class=\"str-chat__channel-list-messenger__main\">\n <ng-content select=\"[channel-list-top]\"></ng-content>\n <div\n *ngIf=\"!(channels$ | async)?.length\"\n class=\"str-chat__channel-list-empty\"\n >\n <stream-icon icon=\"chat-bubble\"></stream-icon>\n <p data-testid=\"empty-channel-list-indicator\">\n {{ \"streamChat.You have no channels currently\" | translate }}\n </p>\n </div>\n <p\n *ngIf=\"!(channels$ | async)?.length\"\n class=\"str-chat__channel-list-empty-v1\"\n data-testid=\"empty-channel-list-indicator\"\n >\n {{ \"streamChat.You have no channels currently\" | translate }}\n </p>\n <ng-container\n *ngFor=\"let channel of channels$ | async; trackBy: trackByChannelId\"\n >\n <ng-template #defaultTemplate let-channelInput=\"channel\">\n <stream-channel-preview\n data-testclass=\"channel-preview\"\n [channel]=\"channelInput\"\n ></stream-channel-preview>\n </ng-template>\n <div>\n <ng-container\n *ngTemplateOutlet=\"\n customChannelPreviewTemplate || defaultTemplate;\n context: { channel: channel }\n \"\n ></ng-container>\n </div>\n </ng-container>\n <div\n *ngIf=\"hasMoreChannels$ | async\"\n class=\"str-chat__load-more-button\"\n data-testid=\"load-more\"\n (click)=\"loadMoreChannels()\"\n (keyup.enter)=\"loadMoreChannels()\"\n >\n <button\n class=\"str-chat__load-more-button__button str-chat__cta-button\"\n data-testid=\"load-more-button\"\n [disabled]=\"isLoadingMoreChannels\"\n >\n <span *ngIf=\"!isLoadingMoreChannels; else loadingIndicator\">{{\n \"Load more\" | translate\n }}</span>\n <ng-template #loadingIndicator\n ><stream-loading-indicator-placeholder></stream-loading-indicator-placeholder\n ></ng-template>\n </button>\n </div>\n <ng-content select=\"[channel-list-bottom]\"></ng-content>\n </div>\n </div>\n</div>\n\n<ng-template #statusIndicator>\n <ng-container *ngIf=\"isError$ | async\">\n <ng-container *ngTemplateOutlet=\"chatDown\"></ng-container>\n </ng-container>\n <ng-container *ngIf=\"isInitializing$ | async\">\n <ng-container *ngTemplateOutlet=\"loadingChannels\"></ng-container>\n </ng-container>\n</ng-template>\n\n<ng-template #chatDown>\n <div data-testid=\"chatdown-container\" class=\"str-chat__down\">\n <ng-container *ngTemplateOutlet=\"loadingChannels\"></ng-container>\n </div>\n</ng-template>\n\n<ng-template #loadingChannels>\n <div data-testid=\"loading-indicator\" class=\"str-chat__loading-channels\">\n <ng-container *ngTemplateOutlet=\"loadingChannel\"></ng-container>\n <ng-container *ngTemplateOutlet=\"loadingChannel\"></ng-container>\n <ng-container *ngTemplateOutlet=\"loadingChannel\"></ng-container>\n </div>\n</ng-template>\n\n<ng-template #loadingChannel>\n <div\n class=\"str-chat__loading-channels-item str-chat__channel-preview-loading\"\n >\n <div class=\"str-chat__loading-channels-avatar\"></div>\n <div\n class=\"str-chat__loading-channels-meta str-chat__channel-preview-end-loading\"\n >\n <div class=\"str-chat__loading-channels-username\"></div>\n <div class=\"str-chat__loading-channels-status\"></div>\n </div>\n </div>\n</ng-template>\n", dependencies: [{ kind: "directive", type: i4.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i4.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: ChannelPreviewComponent, selector: "stream-channel-preview", inputs: ["channel"] }, { kind: "component", type: IconComponent, selector: "stream-icon", inputs: ["icon"] }, { kind: "component", type: LoadingIndicatorPlaceholderComponent, selector: "stream-loading-indicator-placeholder" }, { kind: "pipe", type: i4.AsyncPipe, name: "async" }, { kind: "pipe", type: i10.TranslatePipe, name: "translate" }] });
4183
4211
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.4", ngImport: i0, type: ChannelListComponent, decorators: [{
4184
4212
  type: Component,
4185
- args: [{ selector: 'stream-channel-list', template: "<div\n #container\n data-testid=\"channel-list-container\"\n class=\"str-chat str-chat__channel-list str-chat-channel-list messaging str-chat__theme-{{\n theme$ | async\n }}\"\n>\n <div\n *ngIf=\"\n (isError$ | async) === false && (isInitializing$ | async) === false;\n else statusIndicator\n \"\n class=\"str-chat__channel-list-messenger\"\n >\n <div class=\"str-chat__channel-list-messenger__main\">\n <ng-content select=\"[channel-list-top]\"></ng-content>\n <div\n *ngIf=\"!(channels$ | async)?.length\"\n class=\"str-chat__channel-list-empty\"\n >\n <stream-icon icon=\"chat-bubble\"></stream-icon>\n <p data-testid=\"empty-channel-list-indicator\">\n {{ \"streamChat.You have no channels currently\" | translate }}\n </p>\n </div>\n <p\n *ngIf=\"!(channels$ | async)?.length\"\n class=\"str-chat__channel-list-empty-v1\"\n data-testid=\"empty-channel-list-indicator\"\n >\n {{ \"streamChat.You have no channels currently\" | translate }}\n </p>\n <ng-container\n *ngFor=\"let channel of channels$ | async; trackBy: trackByChannelId\"\n >\n <ng-template #defaultTemplate let-channelInput=\"channel\">\n <stream-channel-preview\n data-testclass=\"channel-preview\"\n [channel]=\"channelInput\"\n ></stream-channel-preview>\n </ng-template>\n <div>\n <ng-container\n *ngTemplateOutlet=\"\n customChannelPreviewTemplate || defaultTemplate;\n context: { channel: channel }\n \"\n ></ng-container>\n </div>\n </ng-container>\n <div\n *ngIf=\"hasMoreChannels$ | async\"\n class=\"str-chat__load-more-button\"\n data-testid=\"load-more\"\n (click)=\"loadMoreChannels()\"\n (keyup.enter)=\"loadMoreChannels()\"\n >\n <button\n class=\"str-chat__load-more-button__button str-chat__cta-button\"\n data-testid=\"load-more-button\"\n [disabled]=\"isLoadingMoreChannels\"\n >\n <span *ngIf=\"!isLoadingMoreChannels; else loadingIndicator\">{{\n \"Load more\" | translate\n }}</span>\n <ng-template #loadingIndicator\n ><stream-loading-indicator-placeholder></stream-loading-indicator-placeholder\n ></ng-template>\n </button>\n </div>\n <ng-content select=\"[channel-list-bottom]\"></ng-content>\n </div>\n </div>\n</div>\n\n<ng-template #statusIndicator>\n <ng-container *ngIf=\"isError$ | async\">\n <ng-container *ngTemplateOutlet=\"chatDown\"></ng-container>\n </ng-container>\n <ng-container *ngIf=\"isInitializing$ | async\">\n <ng-container *ngTemplateOutlet=\"loadingChannels\"></ng-container>\n </ng-container>\n</ng-template>\n\n<ng-template #chatDown>\n <div data-testid=\"chatdown-container\" class=\"str-chat__down\">\n <ng-container *ngTemplateOutlet=\"loadingChannels\"></ng-container>\n </div>\n</ng-template>\n\n<ng-template #loadingChannels>\n <div data-testid=\"loading-indicator\" class=\"str-chat__loading-channels\">\n <ng-container *ngTemplateOutlet=\"loadingChannel\"></ng-container>\n <ng-container *ngTemplateOutlet=\"loadingChannel\"></ng-container>\n <ng-container *ngTemplateOutlet=\"loadingChannel\"></ng-container>\n </div>\n</ng-template>\n\n<ng-template #loadingChannel>\n <div\n class=\"str-chat__loading-channels-item str-chat__channel-preview-loading\"\n >\n <div class=\"str-chat__loading-channels-avatar\"></div>\n <div\n class=\"\n str-chat__loading-channels-meta str-chat__channel-preview-end-loading\n \"\n >\n <div class=\"str-chat__loading-channels-username\"></div>\n <div class=\"str-chat__loading-channels-status\"></div>\n </div>\n </div>\n</ng-template>\n" }]
4213
+ args: [{ selector: 'stream-channel-list', template: "<div\n #container\n data-testid=\"channel-list-container\"\n class=\"str-chat str-chat__channel-list str-chat-channel-list messaging str-chat__theme-{{\n theme$ | async\n }}\"\n>\n <div\n *ngIf=\"\n (isError$ | async) === false && (isInitializing$ | async) === false;\n else statusIndicator\n \"\n class=\"str-chat__channel-list-messenger\"\n >\n <div class=\"str-chat__channel-list-messenger__main\">\n <ng-content select=\"[channel-list-top]\"></ng-content>\n <div\n *ngIf=\"!(channels$ | async)?.length\"\n class=\"str-chat__channel-list-empty\"\n >\n <stream-icon icon=\"chat-bubble\"></stream-icon>\n <p data-testid=\"empty-channel-list-indicator\">\n {{ \"streamChat.You have no channels currently\" | translate }}\n </p>\n </div>\n <p\n *ngIf=\"!(channels$ | async)?.length\"\n class=\"str-chat__channel-list-empty-v1\"\n data-testid=\"empty-channel-list-indicator\"\n >\n {{ \"streamChat.You have no channels currently\" | translate }}\n </p>\n <ng-container\n *ngFor=\"let channel of channels$ | async; trackBy: trackByChannelId\"\n >\n <ng-template #defaultTemplate let-channelInput=\"channel\">\n <stream-channel-preview\n data-testclass=\"channel-preview\"\n [channel]=\"channelInput\"\n ></stream-channel-preview>\n </ng-template>\n <div>\n <ng-container\n *ngTemplateOutlet=\"\n customChannelPreviewTemplate || defaultTemplate;\n context: { channel: channel }\n \"\n ></ng-container>\n </div>\n </ng-container>\n <div\n *ngIf=\"hasMoreChannels$ | async\"\n class=\"str-chat__load-more-button\"\n data-testid=\"load-more\"\n (click)=\"loadMoreChannels()\"\n (keyup.enter)=\"loadMoreChannels()\"\n >\n <button\n class=\"str-chat__load-more-button__button str-chat__cta-button\"\n data-testid=\"load-more-button\"\n [disabled]=\"isLoadingMoreChannels\"\n >\n <span *ngIf=\"!isLoadingMoreChannels; else loadingIndicator\">{{\n \"Load more\" | translate\n }}</span>\n <ng-template #loadingIndicator\n ><stream-loading-indicator-placeholder></stream-loading-indicator-placeholder\n ></ng-template>\n </button>\n </div>\n <ng-content select=\"[channel-list-bottom]\"></ng-content>\n </div>\n </div>\n</div>\n\n<ng-template #statusIndicator>\n <ng-container *ngIf=\"isError$ | async\">\n <ng-container *ngTemplateOutlet=\"chatDown\"></ng-container>\n </ng-container>\n <ng-container *ngIf=\"isInitializing$ | async\">\n <ng-container *ngTemplateOutlet=\"loadingChannels\"></ng-container>\n </ng-container>\n</ng-template>\n\n<ng-template #chatDown>\n <div data-testid=\"chatdown-container\" class=\"str-chat__down\">\n <ng-container *ngTemplateOutlet=\"loadingChannels\"></ng-container>\n </div>\n</ng-template>\n\n<ng-template #loadingChannels>\n <div data-testid=\"loading-indicator\" class=\"str-chat__loading-channels\">\n <ng-container *ngTemplateOutlet=\"loadingChannel\"></ng-container>\n <ng-container *ngTemplateOutlet=\"loadingChannel\"></ng-container>\n <ng-container *ngTemplateOutlet=\"loadingChannel\"></ng-container>\n </div>\n</ng-template>\n\n<ng-template #loadingChannel>\n <div\n class=\"str-chat__loading-channels-item str-chat__channel-preview-loading\"\n >\n <div class=\"str-chat__loading-channels-avatar\"></div>\n <div\n class=\"str-chat__loading-channels-meta str-chat__channel-preview-end-loading\"\n >\n <div class=\"str-chat__loading-channels-username\"></div>\n <div class=\"str-chat__loading-channels-status\"></div>\n </div>\n </div>\n</ng-template>\n" }]
4186
4214
  }], ctorParameters: function () { return [{ type: ChannelService }, { type: CustomTemplatesService }, { type: ThemeService }]; }, propDecorators: { container: [{
4187
4215
  type: ViewChild,
4188
4216
  args: ['container']
@@ -4465,10 +4493,10 @@ class VoiceRecordingComponent {
4465
4493
  }
4466
4494
  }
4467
4495
  VoiceRecordingComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.4", ngImport: i0, type: VoiceRecordingComponent, deps: [{ token: i0.NgZone }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
4468
- VoiceRecordingComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.0.4", type: VoiceRecordingComponent, selector: "stream-voice-recording", inputs: { attachment: "attachment" }, viewQueries: [{ propertyName: "audioElement", first: true, predicate: ["audioElement"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div\n class=\"str-chat__message-attachment__voice-recording-widget\"\n data-testid=\"voice-recording-widget\"\n [class.str-chat__message-attachment__voice-recording-widget--error]=\"isError\"\n>\n <!-- Empty event handlers to trigger change detection -->\n <audio\n #audioElement\n (play)=\"(null)\"\n (pause)=\"(null)\"\n (ended)=\"(null)\"\n (error)=\"isError = true\"\n (abort)=\"isError = true\"\n >\n <source\n data-testid=\"audio-source\"\n [src]=\"attachment?.asset_url\"\n [type]=\"attachment?.mime_type\"\n />\n </audio>\n <button\n class=\"str-chat__message-attachment-audio-widget--play-button\"\n data-testid=\"play-button\"\n (click)=\"togglePlay()\"\n >\n <stream-icon-placeholder\n [icon]=\"audioElement?.paused ? 'play' : 'pause'\"\n ></stream-icon-placeholder>\n </button>\n <div class=\"str-chat__message-attachment__voice-recording-widget__metadata\">\n <div class=\"str-chat__message-attachment-voice-recording-widget--first-row\">\n <div\n class=\"str-chat__message-attachment__voice-recording-widget__title\"\n data-testid=\"voice-recording-title\"\n [title]=\"attachment?.title\"\n >\n {{ attachment?.title }}\n </div>\n </div>\n\n <ng-container *ngIf=\"isError; else state\">\n <div\n class=\"\n str-chat__message-attachment__voice-recording-widget__error-message\n \"\n >\n <stream-icon-placeholder icon=\"error\"></stream-icon-placeholder>\n <span data-testid=\"error-message\">{{\n \"streamChat.Error playing audio\" | translate\n }}</span>\n </div>\n </ng-container>\n <ng-template #state>\n <div\n class=\"\n str-chat__message-attachment__voice-recording-widget__audio-state\n \"\n >\n <div\n class=\"str-chat__message-attachment__voice-recording-widget__timer\"\n >\n <span\n *ngIf=\"!!attachment?.duration; else fileSizeTemplate\"\n data-testid=\"duration\"\n >\n {{\n secondsElapsed > 0 || !audioElement.paused\n ? secondsElapsedFormatted\n : durationFormatted\n }}</span\n >\n <ng-template #fileSizeTemplate>\n <span\n class=\"str-chat__message-attachment-file--item-size\"\n data-testid=\"file-size-indicator\"\n >\n {{ fileSize }}\n </span>\n </ng-template>\n </div>\n <stream-voice-recording-wavebar\n *ngIf=\"attachment?.waveform_data && attachment?.duration\"\n [waveFormData]=\"attachment?.waveform_data || []\"\n [duration]=\"attachment?.duration\"\n [audioElement]=\"audioElement\"\n ></stream-voice-recording-wavebar>\n </div>\n </ng-template>\n </div>\n <div\n class=\"str-chat__message-attachment__voice-recording-widget__right-section\"\n >\n <button\n *ngIf=\"!audioElement?.paused; else fileIcon\"\n class=\"str-chat__message_attachment__playback-rate-button\"\n data-testid=\"playback-rate-button\"\n (click)=\"setPlaybackRate()\"\n >\n {{ audioElement?.playbackRate | number: \"1.1-1\" }}x\n </button>\n <ng-template #fileIcon>\n <stream-icon-placeholder\n class=\"str-chat__attachment-type-icon\"\n icon=\"audio-file\"\n ></stream-icon-placeholder>\n </ng-template>\n </div>\n</div>\n", dependencies: [{ kind: "directive", type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: IconPlaceholderComponent, selector: "stream-icon-placeholder", inputs: ["icon"] }, { kind: "component", type: VoiceRecordingWavebarComponent, selector: "stream-voice-recording-wavebar", inputs: ["audioElement", "waveFormData", "duration"] }, { kind: "pipe", type: i4.DecimalPipe, name: "number" }, { kind: "pipe", type: i10.TranslatePipe, name: "translate" }] });
4496
+ VoiceRecordingComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.0.4", type: VoiceRecordingComponent, selector: "stream-voice-recording", inputs: { attachment: "attachment" }, viewQueries: [{ propertyName: "audioElement", first: true, predicate: ["audioElement"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div\n class=\"str-chat__message-attachment__voice-recording-widget\"\n data-testid=\"voice-recording-widget\"\n [class.str-chat__message-attachment__voice-recording-widget--error]=\"isError\"\n>\n <!-- Empty event handlers to trigger change detection -->\n <audio\n #audioElement\n (play)=\"(null)\"\n (pause)=\"(null)\"\n (ended)=\"(null)\"\n (error)=\"isError = true\"\n (abort)=\"isError = true\"\n >\n <source\n data-testid=\"audio-source\"\n [src]=\"attachment?.asset_url\"\n [type]=\"attachment?.mime_type\"\n />\n </audio>\n <button\n class=\"str-chat__message-attachment-audio-widget--play-button\"\n data-testid=\"play-button\"\n (click)=\"togglePlay()\"\n >\n <stream-icon-placeholder\n [icon]=\"audioElement?.paused ? 'play' : 'pause'\"\n ></stream-icon-placeholder>\n </button>\n <div class=\"str-chat__message-attachment__voice-recording-widget__metadata\">\n <div class=\"str-chat__message-attachment-voice-recording-widget--first-row\">\n <div\n class=\"str-chat__message-attachment__voice-recording-widget__title\"\n data-testid=\"voice-recording-title\"\n [title]=\"attachment?.title\"\n >\n {{ attachment?.title }}\n </div>\n </div>\n\n <ng-container *ngIf=\"isError; else state\">\n <div\n class=\"str-chat__message-attachment__voice-recording-widget__error-message\"\n >\n <stream-icon-placeholder icon=\"error\"></stream-icon-placeholder>\n <span data-testid=\"error-message\">{{\n \"streamChat.Error playing audio\" | translate\n }}</span>\n </div>\n </ng-container>\n <ng-template #state>\n <div\n class=\"str-chat__message-attachment__voice-recording-widget__audio-state\"\n >\n <div\n class=\"str-chat__message-attachment__voice-recording-widget__timer\"\n >\n <span\n *ngIf=\"!!attachment?.duration; else fileSizeTemplate\"\n data-testid=\"duration\"\n >\n {{\n secondsElapsed > 0 || !audioElement.paused\n ? secondsElapsedFormatted\n : durationFormatted\n }}</span\n >\n <ng-template #fileSizeTemplate>\n <span\n class=\"str-chat__message-attachment-file--item-size\"\n data-testid=\"file-size-indicator\"\n >\n {{ fileSize }}\n </span>\n </ng-template>\n </div>\n <stream-voice-recording-wavebar\n *ngIf=\"attachment?.waveform_data && attachment?.duration\"\n [waveFormData]=\"attachment?.waveform_data || []\"\n [duration]=\"attachment?.duration\"\n [audioElement]=\"audioElement\"\n ></stream-voice-recording-wavebar>\n </div>\n </ng-template>\n </div>\n <div\n class=\"str-chat__message-attachment__voice-recording-widget__right-section\"\n >\n <button\n *ngIf=\"!audioElement?.paused; else fileIcon\"\n class=\"str-chat__message_attachment__playback-rate-button\"\n data-testid=\"playback-rate-button\"\n (click)=\"setPlaybackRate()\"\n >\n {{ audioElement?.playbackRate | number : \"1.1-1\" }}x\n </button>\n <ng-template #fileIcon>\n <stream-icon-placeholder\n class=\"str-chat__attachment-type-icon\"\n icon=\"audio-file\"\n ></stream-icon-placeholder>\n </ng-template>\n </div>\n</div>\n", dependencies: [{ kind: "directive", type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: IconPlaceholderComponent, selector: "stream-icon-placeholder", inputs: ["icon"] }, { kind: "component", type: VoiceRecordingWavebarComponent, selector: "stream-voice-recording-wavebar", inputs: ["audioElement", "waveFormData", "duration"] }, { kind: "pipe", type: i4.DecimalPipe, name: "number" }, { kind: "pipe", type: i10.TranslatePipe, name: "translate" }] });
4469
4497
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.4", ngImport: i0, type: VoiceRecordingComponent, decorators: [{
4470
4498
  type: Component,
4471
- args: [{ selector: 'stream-voice-recording', template: "<div\n class=\"str-chat__message-attachment__voice-recording-widget\"\n data-testid=\"voice-recording-widget\"\n [class.str-chat__message-attachment__voice-recording-widget--error]=\"isError\"\n>\n <!-- Empty event handlers to trigger change detection -->\n <audio\n #audioElement\n (play)=\"(null)\"\n (pause)=\"(null)\"\n (ended)=\"(null)\"\n (error)=\"isError = true\"\n (abort)=\"isError = true\"\n >\n <source\n data-testid=\"audio-source\"\n [src]=\"attachment?.asset_url\"\n [type]=\"attachment?.mime_type\"\n />\n </audio>\n <button\n class=\"str-chat__message-attachment-audio-widget--play-button\"\n data-testid=\"play-button\"\n (click)=\"togglePlay()\"\n >\n <stream-icon-placeholder\n [icon]=\"audioElement?.paused ? 'play' : 'pause'\"\n ></stream-icon-placeholder>\n </button>\n <div class=\"str-chat__message-attachment__voice-recording-widget__metadata\">\n <div class=\"str-chat__message-attachment-voice-recording-widget--first-row\">\n <div\n class=\"str-chat__message-attachment__voice-recording-widget__title\"\n data-testid=\"voice-recording-title\"\n [title]=\"attachment?.title\"\n >\n {{ attachment?.title }}\n </div>\n </div>\n\n <ng-container *ngIf=\"isError; else state\">\n <div\n class=\"\n str-chat__message-attachment__voice-recording-widget__error-message\n \"\n >\n <stream-icon-placeholder icon=\"error\"></stream-icon-placeholder>\n <span data-testid=\"error-message\">{{\n \"streamChat.Error playing audio\" | translate\n }}</span>\n </div>\n </ng-container>\n <ng-template #state>\n <div\n class=\"\n str-chat__message-attachment__voice-recording-widget__audio-state\n \"\n >\n <div\n class=\"str-chat__message-attachment__voice-recording-widget__timer\"\n >\n <span\n *ngIf=\"!!attachment?.duration; else fileSizeTemplate\"\n data-testid=\"duration\"\n >\n {{\n secondsElapsed > 0 || !audioElement.paused\n ? secondsElapsedFormatted\n : durationFormatted\n }}</span\n >\n <ng-template #fileSizeTemplate>\n <span\n class=\"str-chat__message-attachment-file--item-size\"\n data-testid=\"file-size-indicator\"\n >\n {{ fileSize }}\n </span>\n </ng-template>\n </div>\n <stream-voice-recording-wavebar\n *ngIf=\"attachment?.waveform_data && attachment?.duration\"\n [waveFormData]=\"attachment?.waveform_data || []\"\n [duration]=\"attachment?.duration\"\n [audioElement]=\"audioElement\"\n ></stream-voice-recording-wavebar>\n </div>\n </ng-template>\n </div>\n <div\n class=\"str-chat__message-attachment__voice-recording-widget__right-section\"\n >\n <button\n *ngIf=\"!audioElement?.paused; else fileIcon\"\n class=\"str-chat__message_attachment__playback-rate-button\"\n data-testid=\"playback-rate-button\"\n (click)=\"setPlaybackRate()\"\n >\n {{ audioElement?.playbackRate | number: \"1.1-1\" }}x\n </button>\n <ng-template #fileIcon>\n <stream-icon-placeholder\n class=\"str-chat__attachment-type-icon\"\n icon=\"audio-file\"\n ></stream-icon-placeholder>\n </ng-template>\n </div>\n</div>\n" }]
4499
+ args: [{ selector: 'stream-voice-recording', template: "<div\n class=\"str-chat__message-attachment__voice-recording-widget\"\n data-testid=\"voice-recording-widget\"\n [class.str-chat__message-attachment__voice-recording-widget--error]=\"isError\"\n>\n <!-- Empty event handlers to trigger change detection -->\n <audio\n #audioElement\n (play)=\"(null)\"\n (pause)=\"(null)\"\n (ended)=\"(null)\"\n (error)=\"isError = true\"\n (abort)=\"isError = true\"\n >\n <source\n data-testid=\"audio-source\"\n [src]=\"attachment?.asset_url\"\n [type]=\"attachment?.mime_type\"\n />\n </audio>\n <button\n class=\"str-chat__message-attachment-audio-widget--play-button\"\n data-testid=\"play-button\"\n (click)=\"togglePlay()\"\n >\n <stream-icon-placeholder\n [icon]=\"audioElement?.paused ? 'play' : 'pause'\"\n ></stream-icon-placeholder>\n </button>\n <div class=\"str-chat__message-attachment__voice-recording-widget__metadata\">\n <div class=\"str-chat__message-attachment-voice-recording-widget--first-row\">\n <div\n class=\"str-chat__message-attachment__voice-recording-widget__title\"\n data-testid=\"voice-recording-title\"\n [title]=\"attachment?.title\"\n >\n {{ attachment?.title }}\n </div>\n </div>\n\n <ng-container *ngIf=\"isError; else state\">\n <div\n class=\"str-chat__message-attachment__voice-recording-widget__error-message\"\n >\n <stream-icon-placeholder icon=\"error\"></stream-icon-placeholder>\n <span data-testid=\"error-message\">{{\n \"streamChat.Error playing audio\" | translate\n }}</span>\n </div>\n </ng-container>\n <ng-template #state>\n <div\n class=\"str-chat__message-attachment__voice-recording-widget__audio-state\"\n >\n <div\n class=\"str-chat__message-attachment__voice-recording-widget__timer\"\n >\n <span\n *ngIf=\"!!attachment?.duration; else fileSizeTemplate\"\n data-testid=\"duration\"\n >\n {{\n secondsElapsed > 0 || !audioElement.paused\n ? secondsElapsedFormatted\n : durationFormatted\n }}</span\n >\n <ng-template #fileSizeTemplate>\n <span\n class=\"str-chat__message-attachment-file--item-size\"\n data-testid=\"file-size-indicator\"\n >\n {{ fileSize }}\n </span>\n </ng-template>\n </div>\n <stream-voice-recording-wavebar\n *ngIf=\"attachment?.waveform_data && attachment?.duration\"\n [waveFormData]=\"attachment?.waveform_data || []\"\n [duration]=\"attachment?.duration\"\n [audioElement]=\"audioElement\"\n ></stream-voice-recording-wavebar>\n </div>\n </ng-template>\n </div>\n <div\n class=\"str-chat__message-attachment__voice-recording-widget__right-section\"\n >\n <button\n *ngIf=\"!audioElement?.paused; else fileIcon\"\n class=\"str-chat__message_attachment__playback-rate-button\"\n data-testid=\"playback-rate-button\"\n (click)=\"setPlaybackRate()\"\n >\n {{ audioElement?.playbackRate | number : \"1.1-1\" }}x\n </button>\n <ng-template #fileIcon>\n <stream-icon-placeholder\n class=\"str-chat__attachment-type-icon\"\n icon=\"audio-file\"\n ></stream-icon-placeholder>\n </ng-template>\n </div>\n</div>\n" }]
4472
4500
  }], ctorParameters: function () { return [{ type: i0.NgZone }, { type: i0.ChangeDetectorRef }]; }, propDecorators: { attachment: [{
4473
4501
  type: Input
4474
4502
  }], audioElement: [{
@@ -4648,10 +4676,10 @@ class AttachmentListComponent {
4648
4676
  }
4649
4677
  }
4650
4678
  AttachmentListComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.4", ngImport: i0, type: AttachmentListComponent, deps: [{ token: CustomTemplatesService }, { token: ChannelService }, { token: AttachmentConfigurationService }], target: i0.ɵɵFactoryTarget.Component });
4651
- AttachmentListComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.0.4", type: AttachmentListComponent, selector: "stream-attachment-list", inputs: { messageId: "messageId", parentMessageId: "parentMessageId", attachments: "attachments" }, outputs: { imageModalStateChange: "imageModalStateChange" }, host: { properties: { "class": "this.class" } }, viewQueries: [{ propertyName: "modalContent", first: true, predicate: ["modalContent"], descendants: true, static: true }], usesOnChanges: true, ngImport: i0, template: "<div *ngIf=\"orderedAttachments.length > 0\" class=\"str-chat__attachment-list\">\n <ng-container\n *ngFor=\"let attachment of orderedAttachments; trackBy: trackByUrl\"\n >\n <div\n data-testclass=\"attachment-container\"\n class=\"str-chat__message-attachment str-chat__message-attachment--{{\n attachment.type\n }} str-chat__message-attachment-dynamic-size\"\n [class.str-chat__message-attachment--card]=\"isCard(attachment)\"\n [class.str-chat-angular__message-attachment-file-single]=\"\n isFile(attachment)\n \"\n [class.str-chat__message-attachment--voice-recording]=\"\n isVoiceMessage(attachment)\n \"\n [class.str-chat__message-attachment-with-actions]=\"\n attachment.actions && attachment.actions.length > 0\n \"\n [class.str-chat__message-attachment--svg-image]=\"isSvg(attachment)\"\n >\n <ng-container *ngIf=\"isImage(attachment)\">\n <ng-container\n *ngTemplateOutlet=\"\n (customTemplatesService.imageAttachmentTemplate$ | async) ||\n defaultImage;\n context: getAttachmentContext(attachment)\n \"\n ></ng-container>\n <ng-template #defaultImage let-attachmentContext=\"attachment\">\n <img\n #imgElement\n class=\"str-chat__message-attachment--img\"\n data-testclass=\"image\"\n [src]=\"\n getImageAttachmentConfiguration(\n attachmentContext,\n 'single',\n imgElement\n ).url\n \"\n [alt]=\"attachmentContext?.fallback\"\n [ngStyle]=\"{\n height: getImageAttachmentConfiguration(\n attachmentContext,\n 'single',\n imgElement\n ).height,\n width: getImageAttachmentConfiguration(\n attachmentContext,\n 'single',\n imgElement\n ).width,\n '--original-height': getImageAttachmentConfiguration(\n attachmentContext,\n 'single',\n imgElement\n ).originalHeight,\n '--original-width': getImageAttachmentConfiguration(\n attachmentContext,\n 'single',\n imgElement\n ).originalWidth\n }\"\n (click)=\"openImageModal([attachmentContext])\"\n (keyup.enter)=\"openImageModal([attachmentContext])\"\n />\n </ng-template>\n </ng-container>\n <ng-container *ngIf=\"isGallery(attachment)\">\n <ng-container\n *ngTemplateOutlet=\"\n (customTemplatesService.galleryAttachmentTemplate$ | async) ||\n defaultGallery;\n context: getAttachmentContext(attachment)\n \"\n ></ng-container>\n <ng-template #defaultGallery let-attachmentContext=\"attachment\">\n <div\n class=\"str-chat__gallery\"\n data-testid=\"image-gallery\"\n [class.str-chat__gallery--square]=\"\n (attachmentContext?.images)!.length > 3\n \"\n [class.str-chat__gallery-two-rows]=\"\n (attachmentContext?.images)!.length > 2\n \"\n >\n <ng-container\n *ngFor=\"\n let galleryImage of attachmentContext.images;\n let index = index;\n let isLast = last;\n trackBy: trackByImageUrl\n \"\n >\n <button\n *ngIf=\"index < 3 || (index === 3 && isLast)\"\n class=\"str-chat__gallery-image\"\n data-testclass=\"gallery-image\"\n [class.str-chat__message-attachment--svg-image]=\"\n isSvg(galleryImage)\n \"\n (click)=\"openImageModal(attachmentContext.images!, index)\"\n (keyup.enter)=\"openImageModal(attachmentContext.images!, index)\"\n >\n <img\n #imgElement\n fetchpriority=\"low\"\n loading=\"lazy\"\n [src]=\"\n getImageAttachmentConfiguration(\n galleryImage,\n 'gallery',\n imgElement\n ).url\n \"\n [alt]=\"galleryImage.fallback\"\n [style.--original-height]=\"\n getImageAttachmentConfiguration(\n galleryImage,\n 'gallery',\n imgElement\n ).originalHeight\n \"\n [style.--original-width]=\"\n getImageAttachmentConfiguration(\n galleryImage,\n 'gallery',\n imgElement\n ).originalWidth\n \"\n [ngStyle]=\"{\n height: getImageAttachmentConfiguration(\n galleryImage,\n 'gallery',\n imgElement\n ).height,\n width: getImageAttachmentConfiguration(\n galleryImage,\n 'gallery',\n imgElement\n ).width\n }\"\n />\n </button>\n <button\n *ngIf=\"index === 3 && !isLast\"\n #element\n class=\"str-chat__gallery-placeholder\"\n data-testclass=\"gallery-image\"\n data-testid=\"more-image-button\"\n [class.str-chat__message-attachment--svg-image]=\"\n isSvg(galleryImage)\n \"\n [ngStyle]=\"{\n 'background-image':\n 'url(' +\n getImageAttachmentConfiguration(\n galleryImage,\n 'gallery',\n element\n ).url +\n ')',\n height: getImageAttachmentConfiguration(\n galleryImage,\n 'gallery',\n element\n ).height,\n width: getImageAttachmentConfiguration(\n galleryImage,\n 'gallery',\n element\n ).width,\n '--original-height': getImageAttachmentConfiguration(\n galleryImage,\n 'gallery',\n element\n ).originalHeight,\n '--original-width': getImageAttachmentConfiguration(\n galleryImage,\n 'gallery',\n element\n ).originalWidth\n }\"\n (click)=\"openImageModal(attachmentContext.images!, index)\"\n (keyup.enter)=\"openImageModal(attachmentContext.images!, index)\"\n >\n <p\n [innerHTML]=\"\n 'streamChat.{{ imageCount }} more'\n | translate\n : { imageCount: attachmentContext!.images!.length - 4 }\n \"\n ></p>\n </button>\n </ng-container>\n </div>\n </ng-template>\n </ng-container>\n <ng-container *ngIf=\"isVideo(attachment)\">\n <ng-container\n *ngTemplateOutlet=\"\n (customTemplatesService.videoAttachmentTemplate$ | async) ||\n defaultVideo;\n context: getAttachmentContext(attachment)\n \"\n ></ng-container>\n <ng-template #defaultVideo let-attachmentContext=\"attachment\">\n <div\n class=\"str-chat__player-wrapper\"\n data-testclass=\"video-attachment-parent\"\n [style.--original-height]=\"\n getVideoAttachmentConfiguration(attachmentContext, videoElement)\n .originalHeight\n \"\n [style.--original-width]=\"\n getVideoAttachmentConfiguration(attachmentContext, videoElement)\n .originalWidth\n \"\n [ngStyle]=\"{\n height: getVideoAttachmentConfiguration(\n attachmentContext,\n videoElement\n ).height,\n width: getVideoAttachmentConfiguration(\n attachmentContext,\n videoElement\n ).width\n }\"\n >\n <video\n #videoElement\n class=\"str-chat__video-angular\"\n controls\n data-testclass=\"video-attachment\"\n [src]=\"\n getVideoAttachmentConfiguration(attachmentContext, videoElement)\n .url\n \"\n [poster]=\"\n getVideoAttachmentConfiguration(attachmentContext, videoElement)\n .thumbUrl\n \"\n ></video>\n </div>\n </ng-template>\n </ng-container>\n <ng-container *ngIf=\"isFile(attachment)\">\n <ng-container\n *ngTemplateOutlet=\"\n (customTemplatesService.fileAttachmentTemplate$ | async) ||\n defaultFile;\n context: getAttachmentContext(attachment)\n \"\n ></ng-container>\n <ng-template #defaultFile let-attachmentContext=\"attachment\">\n <div\n class=\"\n str-chat__message-attachment-file--item\n str-chat-angular__message-attachment-file-single\n \"\n >\n <stream-icon-placeholder\n class=\"str-chat__attachment-type-icon\"\n icon=\"unspecified-filetype\"\n ></stream-icon-placeholder>\n <div class=\"str-chat__message-attachment-file--item-text\">\n <a\n class=\"str-chat__message-attachment-file--item-first-row\"\n data-testclass=\"file-link\"\n target=\"_blank\"\n href=\"{{ attachmentContext.asset_url }}\"\n >\n <div\n data-testclass=\"file-title\"\n class=\"str-chat__message-attachment-file--item-name\"\n >\n {{ attachmentContext.title }}\n </div>\n <stream-icon-placeholder\n class=\"str-chat__message-attachment-download-icon\"\n icon=\"download\"\n ></stream-icon-placeholder>\n </a>\n <span\n *ngIf=\"hasFileSize(attachmentContext)\"\n class=\"str-chat__message-attachment-file--item-size\"\n data-testclass=\"size\"\n >{{ getFileSize(attachmentContext) }}</span\n >\n </div>\n </div>\n </ng-template>\n </ng-container>\n <ng-container *ngIf=\"isVoiceMessage(attachment)\">\n <ng-container\n *ngTemplateOutlet=\"\n (customTemplatesService.voiceRecordingAttachmentTemplate$\n | async) || defaultRecording;\n context: getAttachmentContext(attachment)\n \"\n ></ng-container>\n <ng-template #defaultRecording>\n <stream-voice-recording\n data-testclass=\"voice-recording\"\n [attachment]=\"attachment\"\n ></stream-voice-recording>\n </ng-template>\n </ng-container>\n <ng-container\n *ngIf=\"\n isCard(attachment) &&\n getCardAttachmentConfiguration(attachment) as attachmentConfiguration\n \"\n >\n <ng-container\n *ngTemplateOutlet=\"\n (customTemplatesService.cardAttachmentTemplate$ | async) ||\n defaultCard;\n context: getAttachmentContext(attachment)\n \"\n ></ng-container>\n <ng-template #defaultCard let-attachmentContext=\"attachment\">\n <div\n class=\"str-chat__message-attachment-card str-chat__message-attachment-card--{{\n attachmentContext.type\n }}\"\n >\n <div\n *ngIf=\"attachmentConfiguration.url\"\n class=\"str-chat__message-attachment-card--header\"\n >\n <img\n fetchpriority=\"low\"\n loading=\"lazy\"\n data-testclass=\"card-img\"\n alt=\"{{ attachmentConfiguration.url }}\"\n src=\"{{ attachmentConfiguration.url }}\"\n [ngStyle]=\"{\n height: attachmentConfiguration.height,\n width: attachmentConfiguration.width\n }\"\n />\n </div>\n <div class=\"str-chat__message-attachment-card--content\">\n <div class=\"str-chat__message-attachment-card--flex\">\n <div\n *ngIf=\"attachmentContext.title\"\n data-testclass=\"card-title\"\n class=\"str-chat__message-attachment-card--title\"\n >\n {{ attachmentContext.title }}\n </div>\n <div\n *ngIf=\"attachmentContext.text\"\n class=\"str-chat__message-attachment-card--text\"\n data-testclass=\"card-text\"\n >\n {{ attachmentContext.text }}\n </div>\n <a\n *ngIf=\"\n attachmentContext.title_link ||\n attachmentContext.og_scrape_url\n \"\n class=\"str-chat__message-attachment-card--url\"\n data-testclass=\"url-link\"\n noopener\n noreferrer\n target=\"_blank\"\n href=\"{{\n attachmentContext.title_link ||\n attachmentContext.og_scrape_url\n }}\"\n >\n {{\n trimUrl(\n attachmentContext.title_link ||\n attachmentContext.og_scrape_url\n )\n }}\n </a>\n </div>\n </div>\n </div>\n </ng-template>\n </ng-container>\n <ng-container *ngIf=\"attachment.actions && attachment.actions.length > 0\">\n <ng-container\n *ngTemplateOutlet=\"\n (customTemplatesService.attachmentActionsTemplate$ | async) ||\n defaultActions;\n context: getAttachmentContext(attachment)\n \"\n ></ng-container>\n <ng-template #defaultActions let-attachmentContext=\"attachment\">\n <div class=\"str-chat__message-attachment-actions\">\n <div class=\"str-chat__message-attachment-actions-form\">\n <button\n *ngFor=\"\n let action of attachmentContext.actions;\n trackBy: trackByActionValue\n \"\n data-testclass=\"attachment-action\"\n class=\"str-chat__message-attachment-actions-button str-chat__message-attachment-actions-button--{{\n action.style\n }}\"\n (click)=\"sendAction(action)\"\n (keyup.enter)=\"sendAction(action)\"\n >\n {{ action.text }}\n </button>\n </div>\n </div>\n </ng-template>\n </ng-container>\n </div>\n </ng-container>\n\n <ng-container *ngIf=\"imagesToView && imagesToView.length > 0\">\n <ng-container\n *ngTemplateOutlet=\"\n (customTemplatesService.modalTemplate$ | async) || defaultModal;\n context: getModalContext()\n \"\n ></ng-container>\n </ng-container>\n</div>\n\n<ng-template\n #defaultModal\n let-isOpen=\"isOpen\"\n let-isOpenChangeHandler=\"isOpenChangeHandler\"\n let-content=\"content\"\n>\n <stream-modal\n class=\"stream-chat-angular__image-modal-host\"\n [isOpen]=\"isOpen\"\n [content]=\"content\"\n (isOpenChange)=\"isOpenChangeHandler($event)\"\n >\n </stream-modal>\n</ng-template>\n\n<ng-template #modalContent>\n <div class=\"stream-chat-angular__image-modal str-chat__image-carousel\">\n <img\n #imgElement\n class=\"\n stream-chat-angular__image-modal-image\n str-chat__image-carousel-image\n \"\n data-testid=\"modal-image\"\n [src]=\"\n getCarouselImageAttachmentConfiguration(\n imagesToView[imagesToViewCurrentIndex],\n imgElement\n ).url\n \"\n [style.--original-height]=\"\n getCarouselImageAttachmentConfiguration(\n imagesToView[imagesToViewCurrentIndex],\n imgElement\n ).originalHeight\n \"\n [style.--original-width]=\"\n getCarouselImageAttachmentConfiguration(\n imagesToView[imagesToViewCurrentIndex],\n imgElement\n ).originalWidth\n \"\n [alt]=\"imagesToView[imagesToViewCurrentIndex].fallback\"\n [ngStyle]=\"{\n width: getCarouselImageAttachmentConfiguration(\n imagesToView[imagesToViewCurrentIndex],\n imgElement\n ).width,\n height: getCarouselImageAttachmentConfiguration(\n imagesToView[imagesToViewCurrentIndex],\n imgElement\n ).height\n }\"\n />\n <div>\n <button\n class=\"\n stream-chat-angular__image-modal-stepper\n str-chat__image-carousel-stepper str-chat__image-carousel-stepper-prev\n \"\n data-testid=\"image-modal-prev\"\n type=\"button\"\n [ngStyle]=\"{\n visibility: isImageModalPrevButtonVisible ? 'visible' : 'hidden'\n }\"\n (click)=\"stepImages(-1)\"\n (keyup.enter)=\"stepImages(-1)\"\n >\n <stream-icon-placeholder icon=\"arrow-left\"></stream-icon-placeholder>\n </button>\n <button\n class=\"\n stream-chat-angular__image-modal-stepper\n str-chat__image-carousel-stepper str-chat__image-carousel-stepper-next\n \"\n type=\"button\"\n data-testid=\"image-modal-next\"\n [ngStyle]=\"{\n visibility: isImageModalNextButtonVisible ? 'visible' : 'hidden'\n }\"\n (click)=\"stepImages(1)\"\n (keyup.enter)=\"stepImages(1)\"\n >\n <stream-icon-placeholder icon=\"arrow-right\"></stream-icon-placeholder>\n </button>\n </div>\n </div>\n</ng-template>\n", dependencies: [{ kind: "directive", type: i4.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i4.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i4.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "component", type: ModalComponent, selector: "stream-modal", inputs: ["isOpen", "content"], outputs: ["isOpenChange"] }, { kind: "component", type: IconPlaceholderComponent, selector: "stream-icon-placeholder", inputs: ["icon"] }, { kind: "component", type: VoiceRecordingComponent, selector: "stream-voice-recording", inputs: ["attachment"] }, { kind: "pipe", type: i4.AsyncPipe, name: "async" }, { kind: "pipe", type: i10.TranslatePipe, name: "translate" }] });
4679
+ AttachmentListComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.0.4", type: AttachmentListComponent, selector: "stream-attachment-list", inputs: { messageId: "messageId", parentMessageId: "parentMessageId", attachments: "attachments" }, outputs: { imageModalStateChange: "imageModalStateChange" }, host: { properties: { "class": "this.class" } }, viewQueries: [{ propertyName: "modalContent", first: true, predicate: ["modalContent"], descendants: true, static: true }], usesOnChanges: true, ngImport: i0, template: "<div *ngIf=\"orderedAttachments.length > 0\" class=\"str-chat__attachment-list\">\n <ng-container\n *ngFor=\"let attachment of orderedAttachments; trackBy: trackByUrl\"\n >\n <div\n data-testclass=\"attachment-container\"\n class=\"str-chat__message-attachment str-chat__message-attachment--{{\n attachment.type\n }} str-chat__message-attachment-dynamic-size\"\n [class.str-chat__message-attachment--card]=\"isCard(attachment)\"\n [class.str-chat-angular__message-attachment-file-single]=\"\n isFile(attachment)\n \"\n [class.str-chat__message-attachment--voice-recording]=\"\n isVoiceMessage(attachment)\n \"\n [class.str-chat__message-attachment-with-actions]=\"\n attachment.actions && attachment.actions.length > 0\n \"\n [class.str-chat__message-attachment--svg-image]=\"isSvg(attachment)\"\n >\n <ng-container *ngIf=\"isImage(attachment)\">\n <ng-container\n *ngTemplateOutlet=\"\n (customTemplatesService.imageAttachmentTemplate$ | async) ||\n defaultImage;\n context: getAttachmentContext(attachment)\n \"\n ></ng-container>\n <ng-template #defaultImage let-attachmentContext=\"attachment\">\n <img\n #imgElement\n class=\"str-chat__message-attachment--img\"\n data-testclass=\"image\"\n [src]=\"\n getImageAttachmentConfiguration(\n attachmentContext,\n 'single',\n imgElement\n ).url\n \"\n [alt]=\"attachmentContext?.fallback\"\n [ngStyle]=\"{\n height: getImageAttachmentConfiguration(\n attachmentContext,\n 'single',\n imgElement\n ).height,\n width: getImageAttachmentConfiguration(\n attachmentContext,\n 'single',\n imgElement\n ).width,\n '--original-height': getImageAttachmentConfiguration(\n attachmentContext,\n 'single',\n imgElement\n ).originalHeight,\n '--original-width': getImageAttachmentConfiguration(\n attachmentContext,\n 'single',\n imgElement\n ).originalWidth\n }\"\n (click)=\"openImageModal([attachmentContext])\"\n (keyup.enter)=\"openImageModal([attachmentContext])\"\n />\n </ng-template>\n </ng-container>\n <ng-container *ngIf=\"isGallery(attachment)\">\n <ng-container\n *ngTemplateOutlet=\"\n (customTemplatesService.galleryAttachmentTemplate$ | async) ||\n defaultGallery;\n context: getAttachmentContext(attachment)\n \"\n ></ng-container>\n <ng-template #defaultGallery let-attachmentContext=\"attachment\">\n <div\n class=\"str-chat__gallery\"\n data-testid=\"image-gallery\"\n [class.str-chat__gallery--square]=\"\n (attachmentContext?.images)!.length > 3\n \"\n [class.str-chat__gallery-two-rows]=\"\n (attachmentContext?.images)!.length > 2\n \"\n >\n <ng-container\n *ngFor=\"\n let galleryImage of attachmentContext.images;\n let index = index;\n let isLast = last;\n trackBy: trackByImageUrl\n \"\n >\n <button\n *ngIf=\"index < 3 || (index === 3 && isLast)\"\n class=\"str-chat__gallery-image\"\n data-testclass=\"gallery-image\"\n [class.str-chat__message-attachment--svg-image]=\"\n isSvg(galleryImage)\n \"\n (click)=\"openImageModal(attachmentContext.images!, index)\"\n (keyup.enter)=\"openImageModal(attachmentContext.images!, index)\"\n >\n <img\n #imgElement\n fetchpriority=\"low\"\n loading=\"lazy\"\n [src]=\"\n getImageAttachmentConfiguration(\n galleryImage,\n 'gallery',\n imgElement\n ).url\n \"\n [alt]=\"galleryImage.fallback\"\n [style.--original-height]=\"\n getImageAttachmentConfiguration(\n galleryImage,\n 'gallery',\n imgElement\n ).originalHeight\n \"\n [style.--original-width]=\"\n getImageAttachmentConfiguration(\n galleryImage,\n 'gallery',\n imgElement\n ).originalWidth\n \"\n [ngStyle]=\"{\n height: getImageAttachmentConfiguration(\n galleryImage,\n 'gallery',\n imgElement\n ).height,\n width: getImageAttachmentConfiguration(\n galleryImage,\n 'gallery',\n imgElement\n ).width\n }\"\n />\n </button>\n <button\n *ngIf=\"index === 3 && !isLast\"\n #element\n class=\"str-chat__gallery-placeholder\"\n data-testclass=\"gallery-image\"\n data-testid=\"more-image-button\"\n [class.str-chat__message-attachment--svg-image]=\"\n isSvg(galleryImage)\n \"\n [ngStyle]=\"{\n 'background-image':\n 'url(' +\n getImageAttachmentConfiguration(\n galleryImage,\n 'gallery',\n element\n ).url +\n ')',\n height: getImageAttachmentConfiguration(\n galleryImage,\n 'gallery',\n element\n ).height,\n width: getImageAttachmentConfiguration(\n galleryImage,\n 'gallery',\n element\n ).width,\n '--original-height': getImageAttachmentConfiguration(\n galleryImage,\n 'gallery',\n element\n ).originalHeight,\n '--original-width': getImageAttachmentConfiguration(\n galleryImage,\n 'gallery',\n element\n ).originalWidth\n }\"\n (click)=\"openImageModal(attachmentContext.images!, index)\"\n (keyup.enter)=\"openImageModal(attachmentContext.images!, index)\"\n >\n <p\n [innerHTML]=\"\n 'streamChat.{{ imageCount }} more'\n | translate\n : { imageCount: attachmentContext!.images!.length - 4 }\n \"\n ></p>\n </button>\n </ng-container>\n </div>\n </ng-template>\n </ng-container>\n <ng-container *ngIf=\"isVideo(attachment)\">\n <ng-container\n *ngTemplateOutlet=\"\n (customTemplatesService.videoAttachmentTemplate$ | async) ||\n defaultVideo;\n context: getAttachmentContext(attachment)\n \"\n ></ng-container>\n <ng-template #defaultVideo let-attachmentContext=\"attachment\">\n <div\n class=\"str-chat__player-wrapper\"\n data-testclass=\"video-attachment-parent\"\n [style.--original-height]=\"\n getVideoAttachmentConfiguration(attachmentContext, videoElement)\n .originalHeight\n \"\n [style.--original-width]=\"\n getVideoAttachmentConfiguration(attachmentContext, videoElement)\n .originalWidth\n \"\n [ngStyle]=\"{\n height: getVideoAttachmentConfiguration(\n attachmentContext,\n videoElement\n ).height,\n width: getVideoAttachmentConfiguration(\n attachmentContext,\n videoElement\n ).width\n }\"\n >\n <video\n #videoElement\n class=\"str-chat__video-angular\"\n controls\n data-testclass=\"video-attachment\"\n [src]=\"\n getVideoAttachmentConfiguration(attachmentContext, videoElement)\n .url\n \"\n [poster]=\"\n getVideoAttachmentConfiguration(attachmentContext, videoElement)\n .thumbUrl\n \"\n ></video>\n </div>\n </ng-template>\n </ng-container>\n <ng-container *ngIf=\"isFile(attachment)\">\n <ng-container\n *ngTemplateOutlet=\"\n (customTemplatesService.fileAttachmentTemplate$ | async) ||\n defaultFile;\n context: getAttachmentContext(attachment)\n \"\n ></ng-container>\n <ng-template #defaultFile let-attachmentContext=\"attachment\">\n <div\n class=\"str-chat__message-attachment-file--item str-chat-angular__message-attachment-file-single\"\n >\n <stream-icon-placeholder\n class=\"str-chat__attachment-type-icon\"\n icon=\"unspecified-filetype\"\n ></stream-icon-placeholder>\n <div class=\"str-chat__message-attachment-file--item-text\">\n <a\n class=\"str-chat__message-attachment-file--item-first-row\"\n data-testclass=\"file-link\"\n target=\"_blank\"\n href=\"{{ attachmentContext.asset_url }}\"\n >\n <div\n data-testclass=\"file-title\"\n class=\"str-chat__message-attachment-file--item-name\"\n >\n {{ attachmentContext.title }}\n </div>\n <stream-icon-placeholder\n class=\"str-chat__message-attachment-download-icon\"\n icon=\"download\"\n ></stream-icon-placeholder>\n </a>\n <span\n *ngIf=\"hasFileSize(attachmentContext)\"\n class=\"str-chat__message-attachment-file--item-size\"\n data-testclass=\"size\"\n >{{ getFileSize(attachmentContext) }}</span\n >\n </div>\n </div>\n </ng-template>\n </ng-container>\n <ng-container *ngIf=\"isVoiceMessage(attachment)\">\n <ng-container\n *ngTemplateOutlet=\"\n (customTemplatesService.voiceRecordingAttachmentTemplate$\n | async) || defaultRecording;\n context: getAttachmentContext(attachment)\n \"\n ></ng-container>\n <ng-template #defaultRecording>\n <stream-voice-recording\n data-testclass=\"voice-recording\"\n [attachment]=\"attachment\"\n ></stream-voice-recording>\n </ng-template>\n </ng-container>\n <ng-container\n *ngIf=\"\n isCard(attachment) &&\n getCardAttachmentConfiguration(attachment) as attachmentConfiguration\n \"\n >\n <ng-container\n *ngTemplateOutlet=\"\n (customTemplatesService.cardAttachmentTemplate$ | async) ||\n defaultCard;\n context: getAttachmentContext(attachment)\n \"\n ></ng-container>\n <ng-template #defaultCard let-attachmentContext=\"attachment\">\n <div\n class=\"str-chat__message-attachment-card str-chat__message-attachment-card--{{\n attachmentContext.type\n }}\"\n >\n <div\n *ngIf=\"attachmentConfiguration.url\"\n class=\"str-chat__message-attachment-card--header\"\n >\n <img\n fetchpriority=\"low\"\n loading=\"lazy\"\n data-testclass=\"card-img\"\n alt=\"{{ attachmentConfiguration.url }}\"\n src=\"{{ attachmentConfiguration.url }}\"\n [ngStyle]=\"{\n height: attachmentConfiguration.height,\n width: attachmentConfiguration.width\n }\"\n />\n </div>\n <div class=\"str-chat__message-attachment-card--content\">\n <div class=\"str-chat__message-attachment-card--flex\">\n <div\n *ngIf=\"attachmentContext.title\"\n data-testclass=\"card-title\"\n class=\"str-chat__message-attachment-card--title\"\n >\n {{ attachmentContext.title }}\n </div>\n <div\n *ngIf=\"attachmentContext.text\"\n class=\"str-chat__message-attachment-card--text\"\n data-testclass=\"card-text\"\n >\n {{ attachmentContext.text }}\n </div>\n <a\n *ngIf=\"\n attachmentContext.title_link ||\n attachmentContext.og_scrape_url\n \"\n class=\"str-chat__message-attachment-card--url\"\n data-testclass=\"url-link\"\n noopener\n noreferrer\n target=\"_blank\"\n href=\"{{\n attachmentContext.title_link ||\n attachmentContext.og_scrape_url\n }}\"\n >\n {{\n trimUrl(\n attachmentContext.title_link ||\n attachmentContext.og_scrape_url\n )\n }}\n </a>\n </div>\n </div>\n </div>\n </ng-template>\n </ng-container>\n <ng-container *ngIf=\"attachment.actions && attachment.actions.length > 0\">\n <ng-container\n *ngTemplateOutlet=\"\n (customTemplatesService.attachmentActionsTemplate$ | async) ||\n defaultActions;\n context: getAttachmentContext(attachment)\n \"\n ></ng-container>\n <ng-template #defaultActions let-attachmentContext=\"attachment\">\n <div class=\"str-chat__message-attachment-actions\">\n <div class=\"str-chat__message-attachment-actions-form\">\n <button\n *ngFor=\"\n let action of attachmentContext.actions;\n trackBy: trackByActionValue\n \"\n data-testclass=\"attachment-action\"\n class=\"str-chat__message-attachment-actions-button str-chat__message-attachment-actions-button--{{\n action.style\n }}\"\n (click)=\"sendAction(action)\"\n (keyup.enter)=\"sendAction(action)\"\n >\n {{ action.text }}\n </button>\n </div>\n </div>\n </ng-template>\n </ng-container>\n </div>\n </ng-container>\n\n <ng-container *ngIf=\"imagesToView && imagesToView.length > 0\">\n <ng-container\n *ngTemplateOutlet=\"\n (customTemplatesService.modalTemplate$ | async) || defaultModal;\n context: getModalContext()\n \"\n ></ng-container>\n </ng-container>\n</div>\n\n<ng-template\n #defaultModal\n let-isOpen=\"isOpen\"\n let-isOpenChangeHandler=\"isOpenChangeHandler\"\n let-content=\"content\"\n>\n <stream-modal\n class=\"stream-chat-angular__image-modal-host\"\n [isOpen]=\"isOpen\"\n [content]=\"content\"\n (isOpenChange)=\"isOpenChangeHandler($event)\"\n >\n </stream-modal>\n</ng-template>\n\n<ng-template #modalContent>\n <div class=\"stream-chat-angular__image-modal str-chat__image-carousel\">\n <img\n #imgElement\n class=\"stream-chat-angular__image-modal-image str-chat__image-carousel-image\"\n data-testid=\"modal-image\"\n [src]=\"\n getCarouselImageAttachmentConfiguration(\n imagesToView[imagesToViewCurrentIndex],\n imgElement\n ).url\n \"\n [style.--original-height]=\"\n getCarouselImageAttachmentConfiguration(\n imagesToView[imagesToViewCurrentIndex],\n imgElement\n ).originalHeight\n \"\n [style.--original-width]=\"\n getCarouselImageAttachmentConfiguration(\n imagesToView[imagesToViewCurrentIndex],\n imgElement\n ).originalWidth\n \"\n [alt]=\"imagesToView[imagesToViewCurrentIndex].fallback\"\n [ngStyle]=\"{\n width: getCarouselImageAttachmentConfiguration(\n imagesToView[imagesToViewCurrentIndex],\n imgElement\n ).width,\n height: getCarouselImageAttachmentConfiguration(\n imagesToView[imagesToViewCurrentIndex],\n imgElement\n ).height\n }\"\n />\n <div>\n <button\n class=\"stream-chat-angular__image-modal-stepper str-chat__image-carousel-stepper str-chat__image-carousel-stepper-prev\"\n data-testid=\"image-modal-prev\"\n type=\"button\"\n [ngStyle]=\"{\n visibility: isImageModalPrevButtonVisible ? 'visible' : 'hidden'\n }\"\n (click)=\"stepImages(-1)\"\n (keyup.enter)=\"stepImages(-1)\"\n >\n <stream-icon-placeholder icon=\"arrow-left\"></stream-icon-placeholder>\n </button>\n <button\n class=\"stream-chat-angular__image-modal-stepper str-chat__image-carousel-stepper str-chat__image-carousel-stepper-next\"\n type=\"button\"\n data-testid=\"image-modal-next\"\n [ngStyle]=\"{\n visibility: isImageModalNextButtonVisible ? 'visible' : 'hidden'\n }\"\n (click)=\"stepImages(1)\"\n (keyup.enter)=\"stepImages(1)\"\n >\n <stream-icon-placeholder icon=\"arrow-right\"></stream-icon-placeholder>\n </button>\n </div>\n </div>\n</ng-template>\n", dependencies: [{ kind: "directive", type: i4.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i4.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i4.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "component", type: ModalComponent, selector: "stream-modal", inputs: ["isOpen", "content"], outputs: ["isOpenChange"] }, { kind: "component", type: IconPlaceholderComponent, selector: "stream-icon-placeholder", inputs: ["icon"] }, { kind: "component", type: VoiceRecordingComponent, selector: "stream-voice-recording", inputs: ["attachment"] }, { kind: "pipe", type: i4.AsyncPipe, name: "async" }, { kind: "pipe", type: i10.TranslatePipe, name: "translate" }] });
4652
4680
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.4", ngImport: i0, type: AttachmentListComponent, decorators: [{
4653
4681
  type: Component,
4654
- args: [{ selector: 'stream-attachment-list', template: "<div *ngIf=\"orderedAttachments.length > 0\" class=\"str-chat__attachment-list\">\n <ng-container\n *ngFor=\"let attachment of orderedAttachments; trackBy: trackByUrl\"\n >\n <div\n data-testclass=\"attachment-container\"\n class=\"str-chat__message-attachment str-chat__message-attachment--{{\n attachment.type\n }} str-chat__message-attachment-dynamic-size\"\n [class.str-chat__message-attachment--card]=\"isCard(attachment)\"\n [class.str-chat-angular__message-attachment-file-single]=\"\n isFile(attachment)\n \"\n [class.str-chat__message-attachment--voice-recording]=\"\n isVoiceMessage(attachment)\n \"\n [class.str-chat__message-attachment-with-actions]=\"\n attachment.actions && attachment.actions.length > 0\n \"\n [class.str-chat__message-attachment--svg-image]=\"isSvg(attachment)\"\n >\n <ng-container *ngIf=\"isImage(attachment)\">\n <ng-container\n *ngTemplateOutlet=\"\n (customTemplatesService.imageAttachmentTemplate$ | async) ||\n defaultImage;\n context: getAttachmentContext(attachment)\n \"\n ></ng-container>\n <ng-template #defaultImage let-attachmentContext=\"attachment\">\n <img\n #imgElement\n class=\"str-chat__message-attachment--img\"\n data-testclass=\"image\"\n [src]=\"\n getImageAttachmentConfiguration(\n attachmentContext,\n 'single',\n imgElement\n ).url\n \"\n [alt]=\"attachmentContext?.fallback\"\n [ngStyle]=\"{\n height: getImageAttachmentConfiguration(\n attachmentContext,\n 'single',\n imgElement\n ).height,\n width: getImageAttachmentConfiguration(\n attachmentContext,\n 'single',\n imgElement\n ).width,\n '--original-height': getImageAttachmentConfiguration(\n attachmentContext,\n 'single',\n imgElement\n ).originalHeight,\n '--original-width': getImageAttachmentConfiguration(\n attachmentContext,\n 'single',\n imgElement\n ).originalWidth\n }\"\n (click)=\"openImageModal([attachmentContext])\"\n (keyup.enter)=\"openImageModal([attachmentContext])\"\n />\n </ng-template>\n </ng-container>\n <ng-container *ngIf=\"isGallery(attachment)\">\n <ng-container\n *ngTemplateOutlet=\"\n (customTemplatesService.galleryAttachmentTemplate$ | async) ||\n defaultGallery;\n context: getAttachmentContext(attachment)\n \"\n ></ng-container>\n <ng-template #defaultGallery let-attachmentContext=\"attachment\">\n <div\n class=\"str-chat__gallery\"\n data-testid=\"image-gallery\"\n [class.str-chat__gallery--square]=\"\n (attachmentContext?.images)!.length > 3\n \"\n [class.str-chat__gallery-two-rows]=\"\n (attachmentContext?.images)!.length > 2\n \"\n >\n <ng-container\n *ngFor=\"\n let galleryImage of attachmentContext.images;\n let index = index;\n let isLast = last;\n trackBy: trackByImageUrl\n \"\n >\n <button\n *ngIf=\"index < 3 || (index === 3 && isLast)\"\n class=\"str-chat__gallery-image\"\n data-testclass=\"gallery-image\"\n [class.str-chat__message-attachment--svg-image]=\"\n isSvg(galleryImage)\n \"\n (click)=\"openImageModal(attachmentContext.images!, index)\"\n (keyup.enter)=\"openImageModal(attachmentContext.images!, index)\"\n >\n <img\n #imgElement\n fetchpriority=\"low\"\n loading=\"lazy\"\n [src]=\"\n getImageAttachmentConfiguration(\n galleryImage,\n 'gallery',\n imgElement\n ).url\n \"\n [alt]=\"galleryImage.fallback\"\n [style.--original-height]=\"\n getImageAttachmentConfiguration(\n galleryImage,\n 'gallery',\n imgElement\n ).originalHeight\n \"\n [style.--original-width]=\"\n getImageAttachmentConfiguration(\n galleryImage,\n 'gallery',\n imgElement\n ).originalWidth\n \"\n [ngStyle]=\"{\n height: getImageAttachmentConfiguration(\n galleryImage,\n 'gallery',\n imgElement\n ).height,\n width: getImageAttachmentConfiguration(\n galleryImage,\n 'gallery',\n imgElement\n ).width\n }\"\n />\n </button>\n <button\n *ngIf=\"index === 3 && !isLast\"\n #element\n class=\"str-chat__gallery-placeholder\"\n data-testclass=\"gallery-image\"\n data-testid=\"more-image-button\"\n [class.str-chat__message-attachment--svg-image]=\"\n isSvg(galleryImage)\n \"\n [ngStyle]=\"{\n 'background-image':\n 'url(' +\n getImageAttachmentConfiguration(\n galleryImage,\n 'gallery',\n element\n ).url +\n ')',\n height: getImageAttachmentConfiguration(\n galleryImage,\n 'gallery',\n element\n ).height,\n width: getImageAttachmentConfiguration(\n galleryImage,\n 'gallery',\n element\n ).width,\n '--original-height': getImageAttachmentConfiguration(\n galleryImage,\n 'gallery',\n element\n ).originalHeight,\n '--original-width': getImageAttachmentConfiguration(\n galleryImage,\n 'gallery',\n element\n ).originalWidth\n }\"\n (click)=\"openImageModal(attachmentContext.images!, index)\"\n (keyup.enter)=\"openImageModal(attachmentContext.images!, index)\"\n >\n <p\n [innerHTML]=\"\n 'streamChat.{{ imageCount }} more'\n | translate\n : { imageCount: attachmentContext!.images!.length - 4 }\n \"\n ></p>\n </button>\n </ng-container>\n </div>\n </ng-template>\n </ng-container>\n <ng-container *ngIf=\"isVideo(attachment)\">\n <ng-container\n *ngTemplateOutlet=\"\n (customTemplatesService.videoAttachmentTemplate$ | async) ||\n defaultVideo;\n context: getAttachmentContext(attachment)\n \"\n ></ng-container>\n <ng-template #defaultVideo let-attachmentContext=\"attachment\">\n <div\n class=\"str-chat__player-wrapper\"\n data-testclass=\"video-attachment-parent\"\n [style.--original-height]=\"\n getVideoAttachmentConfiguration(attachmentContext, videoElement)\n .originalHeight\n \"\n [style.--original-width]=\"\n getVideoAttachmentConfiguration(attachmentContext, videoElement)\n .originalWidth\n \"\n [ngStyle]=\"{\n height: getVideoAttachmentConfiguration(\n attachmentContext,\n videoElement\n ).height,\n width: getVideoAttachmentConfiguration(\n attachmentContext,\n videoElement\n ).width\n }\"\n >\n <video\n #videoElement\n class=\"str-chat__video-angular\"\n controls\n data-testclass=\"video-attachment\"\n [src]=\"\n getVideoAttachmentConfiguration(attachmentContext, videoElement)\n .url\n \"\n [poster]=\"\n getVideoAttachmentConfiguration(attachmentContext, videoElement)\n .thumbUrl\n \"\n ></video>\n </div>\n </ng-template>\n </ng-container>\n <ng-container *ngIf=\"isFile(attachment)\">\n <ng-container\n *ngTemplateOutlet=\"\n (customTemplatesService.fileAttachmentTemplate$ | async) ||\n defaultFile;\n context: getAttachmentContext(attachment)\n \"\n ></ng-container>\n <ng-template #defaultFile let-attachmentContext=\"attachment\">\n <div\n class=\"\n str-chat__message-attachment-file--item\n str-chat-angular__message-attachment-file-single\n \"\n >\n <stream-icon-placeholder\n class=\"str-chat__attachment-type-icon\"\n icon=\"unspecified-filetype\"\n ></stream-icon-placeholder>\n <div class=\"str-chat__message-attachment-file--item-text\">\n <a\n class=\"str-chat__message-attachment-file--item-first-row\"\n data-testclass=\"file-link\"\n target=\"_blank\"\n href=\"{{ attachmentContext.asset_url }}\"\n >\n <div\n data-testclass=\"file-title\"\n class=\"str-chat__message-attachment-file--item-name\"\n >\n {{ attachmentContext.title }}\n </div>\n <stream-icon-placeholder\n class=\"str-chat__message-attachment-download-icon\"\n icon=\"download\"\n ></stream-icon-placeholder>\n </a>\n <span\n *ngIf=\"hasFileSize(attachmentContext)\"\n class=\"str-chat__message-attachment-file--item-size\"\n data-testclass=\"size\"\n >{{ getFileSize(attachmentContext) }}</span\n >\n </div>\n </div>\n </ng-template>\n </ng-container>\n <ng-container *ngIf=\"isVoiceMessage(attachment)\">\n <ng-container\n *ngTemplateOutlet=\"\n (customTemplatesService.voiceRecordingAttachmentTemplate$\n | async) || defaultRecording;\n context: getAttachmentContext(attachment)\n \"\n ></ng-container>\n <ng-template #defaultRecording>\n <stream-voice-recording\n data-testclass=\"voice-recording\"\n [attachment]=\"attachment\"\n ></stream-voice-recording>\n </ng-template>\n </ng-container>\n <ng-container\n *ngIf=\"\n isCard(attachment) &&\n getCardAttachmentConfiguration(attachment) as attachmentConfiguration\n \"\n >\n <ng-container\n *ngTemplateOutlet=\"\n (customTemplatesService.cardAttachmentTemplate$ | async) ||\n defaultCard;\n context: getAttachmentContext(attachment)\n \"\n ></ng-container>\n <ng-template #defaultCard let-attachmentContext=\"attachment\">\n <div\n class=\"str-chat__message-attachment-card str-chat__message-attachment-card--{{\n attachmentContext.type\n }}\"\n >\n <div\n *ngIf=\"attachmentConfiguration.url\"\n class=\"str-chat__message-attachment-card--header\"\n >\n <img\n fetchpriority=\"low\"\n loading=\"lazy\"\n data-testclass=\"card-img\"\n alt=\"{{ attachmentConfiguration.url }}\"\n src=\"{{ attachmentConfiguration.url }}\"\n [ngStyle]=\"{\n height: attachmentConfiguration.height,\n width: attachmentConfiguration.width\n }\"\n />\n </div>\n <div class=\"str-chat__message-attachment-card--content\">\n <div class=\"str-chat__message-attachment-card--flex\">\n <div\n *ngIf=\"attachmentContext.title\"\n data-testclass=\"card-title\"\n class=\"str-chat__message-attachment-card--title\"\n >\n {{ attachmentContext.title }}\n </div>\n <div\n *ngIf=\"attachmentContext.text\"\n class=\"str-chat__message-attachment-card--text\"\n data-testclass=\"card-text\"\n >\n {{ attachmentContext.text }}\n </div>\n <a\n *ngIf=\"\n attachmentContext.title_link ||\n attachmentContext.og_scrape_url\n \"\n class=\"str-chat__message-attachment-card--url\"\n data-testclass=\"url-link\"\n noopener\n noreferrer\n target=\"_blank\"\n href=\"{{\n attachmentContext.title_link ||\n attachmentContext.og_scrape_url\n }}\"\n >\n {{\n trimUrl(\n attachmentContext.title_link ||\n attachmentContext.og_scrape_url\n )\n }}\n </a>\n </div>\n </div>\n </div>\n </ng-template>\n </ng-container>\n <ng-container *ngIf=\"attachment.actions && attachment.actions.length > 0\">\n <ng-container\n *ngTemplateOutlet=\"\n (customTemplatesService.attachmentActionsTemplate$ | async) ||\n defaultActions;\n context: getAttachmentContext(attachment)\n \"\n ></ng-container>\n <ng-template #defaultActions let-attachmentContext=\"attachment\">\n <div class=\"str-chat__message-attachment-actions\">\n <div class=\"str-chat__message-attachment-actions-form\">\n <button\n *ngFor=\"\n let action of attachmentContext.actions;\n trackBy: trackByActionValue\n \"\n data-testclass=\"attachment-action\"\n class=\"str-chat__message-attachment-actions-button str-chat__message-attachment-actions-button--{{\n action.style\n }}\"\n (click)=\"sendAction(action)\"\n (keyup.enter)=\"sendAction(action)\"\n >\n {{ action.text }}\n </button>\n </div>\n </div>\n </ng-template>\n </ng-container>\n </div>\n </ng-container>\n\n <ng-container *ngIf=\"imagesToView && imagesToView.length > 0\">\n <ng-container\n *ngTemplateOutlet=\"\n (customTemplatesService.modalTemplate$ | async) || defaultModal;\n context: getModalContext()\n \"\n ></ng-container>\n </ng-container>\n</div>\n\n<ng-template\n #defaultModal\n let-isOpen=\"isOpen\"\n let-isOpenChangeHandler=\"isOpenChangeHandler\"\n let-content=\"content\"\n>\n <stream-modal\n class=\"stream-chat-angular__image-modal-host\"\n [isOpen]=\"isOpen\"\n [content]=\"content\"\n (isOpenChange)=\"isOpenChangeHandler($event)\"\n >\n </stream-modal>\n</ng-template>\n\n<ng-template #modalContent>\n <div class=\"stream-chat-angular__image-modal str-chat__image-carousel\">\n <img\n #imgElement\n class=\"\n stream-chat-angular__image-modal-image\n str-chat__image-carousel-image\n \"\n data-testid=\"modal-image\"\n [src]=\"\n getCarouselImageAttachmentConfiguration(\n imagesToView[imagesToViewCurrentIndex],\n imgElement\n ).url\n \"\n [style.--original-height]=\"\n getCarouselImageAttachmentConfiguration(\n imagesToView[imagesToViewCurrentIndex],\n imgElement\n ).originalHeight\n \"\n [style.--original-width]=\"\n getCarouselImageAttachmentConfiguration(\n imagesToView[imagesToViewCurrentIndex],\n imgElement\n ).originalWidth\n \"\n [alt]=\"imagesToView[imagesToViewCurrentIndex].fallback\"\n [ngStyle]=\"{\n width: getCarouselImageAttachmentConfiguration(\n imagesToView[imagesToViewCurrentIndex],\n imgElement\n ).width,\n height: getCarouselImageAttachmentConfiguration(\n imagesToView[imagesToViewCurrentIndex],\n imgElement\n ).height\n }\"\n />\n <div>\n <button\n class=\"\n stream-chat-angular__image-modal-stepper\n str-chat__image-carousel-stepper str-chat__image-carousel-stepper-prev\n \"\n data-testid=\"image-modal-prev\"\n type=\"button\"\n [ngStyle]=\"{\n visibility: isImageModalPrevButtonVisible ? 'visible' : 'hidden'\n }\"\n (click)=\"stepImages(-1)\"\n (keyup.enter)=\"stepImages(-1)\"\n >\n <stream-icon-placeholder icon=\"arrow-left\"></stream-icon-placeholder>\n </button>\n <button\n class=\"\n stream-chat-angular__image-modal-stepper\n str-chat__image-carousel-stepper str-chat__image-carousel-stepper-next\n \"\n type=\"button\"\n data-testid=\"image-modal-next\"\n [ngStyle]=\"{\n visibility: isImageModalNextButtonVisible ? 'visible' : 'hidden'\n }\"\n (click)=\"stepImages(1)\"\n (keyup.enter)=\"stepImages(1)\"\n >\n <stream-icon-placeholder icon=\"arrow-right\"></stream-icon-placeholder>\n </button>\n </div>\n </div>\n</ng-template>\n" }]
4682
+ args: [{ selector: 'stream-attachment-list', template: "<div *ngIf=\"orderedAttachments.length > 0\" class=\"str-chat__attachment-list\">\n <ng-container\n *ngFor=\"let attachment of orderedAttachments; trackBy: trackByUrl\"\n >\n <div\n data-testclass=\"attachment-container\"\n class=\"str-chat__message-attachment str-chat__message-attachment--{{\n attachment.type\n }} str-chat__message-attachment-dynamic-size\"\n [class.str-chat__message-attachment--card]=\"isCard(attachment)\"\n [class.str-chat-angular__message-attachment-file-single]=\"\n isFile(attachment)\n \"\n [class.str-chat__message-attachment--voice-recording]=\"\n isVoiceMessage(attachment)\n \"\n [class.str-chat__message-attachment-with-actions]=\"\n attachment.actions && attachment.actions.length > 0\n \"\n [class.str-chat__message-attachment--svg-image]=\"isSvg(attachment)\"\n >\n <ng-container *ngIf=\"isImage(attachment)\">\n <ng-container\n *ngTemplateOutlet=\"\n (customTemplatesService.imageAttachmentTemplate$ | async) ||\n defaultImage;\n context: getAttachmentContext(attachment)\n \"\n ></ng-container>\n <ng-template #defaultImage let-attachmentContext=\"attachment\">\n <img\n #imgElement\n class=\"str-chat__message-attachment--img\"\n data-testclass=\"image\"\n [src]=\"\n getImageAttachmentConfiguration(\n attachmentContext,\n 'single',\n imgElement\n ).url\n \"\n [alt]=\"attachmentContext?.fallback\"\n [ngStyle]=\"{\n height: getImageAttachmentConfiguration(\n attachmentContext,\n 'single',\n imgElement\n ).height,\n width: getImageAttachmentConfiguration(\n attachmentContext,\n 'single',\n imgElement\n ).width,\n '--original-height': getImageAttachmentConfiguration(\n attachmentContext,\n 'single',\n imgElement\n ).originalHeight,\n '--original-width': getImageAttachmentConfiguration(\n attachmentContext,\n 'single',\n imgElement\n ).originalWidth\n }\"\n (click)=\"openImageModal([attachmentContext])\"\n (keyup.enter)=\"openImageModal([attachmentContext])\"\n />\n </ng-template>\n </ng-container>\n <ng-container *ngIf=\"isGallery(attachment)\">\n <ng-container\n *ngTemplateOutlet=\"\n (customTemplatesService.galleryAttachmentTemplate$ | async) ||\n defaultGallery;\n context: getAttachmentContext(attachment)\n \"\n ></ng-container>\n <ng-template #defaultGallery let-attachmentContext=\"attachment\">\n <div\n class=\"str-chat__gallery\"\n data-testid=\"image-gallery\"\n [class.str-chat__gallery--square]=\"\n (attachmentContext?.images)!.length > 3\n \"\n [class.str-chat__gallery-two-rows]=\"\n (attachmentContext?.images)!.length > 2\n \"\n >\n <ng-container\n *ngFor=\"\n let galleryImage of attachmentContext.images;\n let index = index;\n let isLast = last;\n trackBy: trackByImageUrl\n \"\n >\n <button\n *ngIf=\"index < 3 || (index === 3 && isLast)\"\n class=\"str-chat__gallery-image\"\n data-testclass=\"gallery-image\"\n [class.str-chat__message-attachment--svg-image]=\"\n isSvg(galleryImage)\n \"\n (click)=\"openImageModal(attachmentContext.images!, index)\"\n (keyup.enter)=\"openImageModal(attachmentContext.images!, index)\"\n >\n <img\n #imgElement\n fetchpriority=\"low\"\n loading=\"lazy\"\n [src]=\"\n getImageAttachmentConfiguration(\n galleryImage,\n 'gallery',\n imgElement\n ).url\n \"\n [alt]=\"galleryImage.fallback\"\n [style.--original-height]=\"\n getImageAttachmentConfiguration(\n galleryImage,\n 'gallery',\n imgElement\n ).originalHeight\n \"\n [style.--original-width]=\"\n getImageAttachmentConfiguration(\n galleryImage,\n 'gallery',\n imgElement\n ).originalWidth\n \"\n [ngStyle]=\"{\n height: getImageAttachmentConfiguration(\n galleryImage,\n 'gallery',\n imgElement\n ).height,\n width: getImageAttachmentConfiguration(\n galleryImage,\n 'gallery',\n imgElement\n ).width\n }\"\n />\n </button>\n <button\n *ngIf=\"index === 3 && !isLast\"\n #element\n class=\"str-chat__gallery-placeholder\"\n data-testclass=\"gallery-image\"\n data-testid=\"more-image-button\"\n [class.str-chat__message-attachment--svg-image]=\"\n isSvg(galleryImage)\n \"\n [ngStyle]=\"{\n 'background-image':\n 'url(' +\n getImageAttachmentConfiguration(\n galleryImage,\n 'gallery',\n element\n ).url +\n ')',\n height: getImageAttachmentConfiguration(\n galleryImage,\n 'gallery',\n element\n ).height,\n width: getImageAttachmentConfiguration(\n galleryImage,\n 'gallery',\n element\n ).width,\n '--original-height': getImageAttachmentConfiguration(\n galleryImage,\n 'gallery',\n element\n ).originalHeight,\n '--original-width': getImageAttachmentConfiguration(\n galleryImage,\n 'gallery',\n element\n ).originalWidth\n }\"\n (click)=\"openImageModal(attachmentContext.images!, index)\"\n (keyup.enter)=\"openImageModal(attachmentContext.images!, index)\"\n >\n <p\n [innerHTML]=\"\n 'streamChat.{{ imageCount }} more'\n | translate\n : { imageCount: attachmentContext!.images!.length - 4 }\n \"\n ></p>\n </button>\n </ng-container>\n </div>\n </ng-template>\n </ng-container>\n <ng-container *ngIf=\"isVideo(attachment)\">\n <ng-container\n *ngTemplateOutlet=\"\n (customTemplatesService.videoAttachmentTemplate$ | async) ||\n defaultVideo;\n context: getAttachmentContext(attachment)\n \"\n ></ng-container>\n <ng-template #defaultVideo let-attachmentContext=\"attachment\">\n <div\n class=\"str-chat__player-wrapper\"\n data-testclass=\"video-attachment-parent\"\n [style.--original-height]=\"\n getVideoAttachmentConfiguration(attachmentContext, videoElement)\n .originalHeight\n \"\n [style.--original-width]=\"\n getVideoAttachmentConfiguration(attachmentContext, videoElement)\n .originalWidth\n \"\n [ngStyle]=\"{\n height: getVideoAttachmentConfiguration(\n attachmentContext,\n videoElement\n ).height,\n width: getVideoAttachmentConfiguration(\n attachmentContext,\n videoElement\n ).width\n }\"\n >\n <video\n #videoElement\n class=\"str-chat__video-angular\"\n controls\n data-testclass=\"video-attachment\"\n [src]=\"\n getVideoAttachmentConfiguration(attachmentContext, videoElement)\n .url\n \"\n [poster]=\"\n getVideoAttachmentConfiguration(attachmentContext, videoElement)\n .thumbUrl\n \"\n ></video>\n </div>\n </ng-template>\n </ng-container>\n <ng-container *ngIf=\"isFile(attachment)\">\n <ng-container\n *ngTemplateOutlet=\"\n (customTemplatesService.fileAttachmentTemplate$ | async) ||\n defaultFile;\n context: getAttachmentContext(attachment)\n \"\n ></ng-container>\n <ng-template #defaultFile let-attachmentContext=\"attachment\">\n <div\n class=\"str-chat__message-attachment-file--item str-chat-angular__message-attachment-file-single\"\n >\n <stream-icon-placeholder\n class=\"str-chat__attachment-type-icon\"\n icon=\"unspecified-filetype\"\n ></stream-icon-placeholder>\n <div class=\"str-chat__message-attachment-file--item-text\">\n <a\n class=\"str-chat__message-attachment-file--item-first-row\"\n data-testclass=\"file-link\"\n target=\"_blank\"\n href=\"{{ attachmentContext.asset_url }}\"\n >\n <div\n data-testclass=\"file-title\"\n class=\"str-chat__message-attachment-file--item-name\"\n >\n {{ attachmentContext.title }}\n </div>\n <stream-icon-placeholder\n class=\"str-chat__message-attachment-download-icon\"\n icon=\"download\"\n ></stream-icon-placeholder>\n </a>\n <span\n *ngIf=\"hasFileSize(attachmentContext)\"\n class=\"str-chat__message-attachment-file--item-size\"\n data-testclass=\"size\"\n >{{ getFileSize(attachmentContext) }}</span\n >\n </div>\n </div>\n </ng-template>\n </ng-container>\n <ng-container *ngIf=\"isVoiceMessage(attachment)\">\n <ng-container\n *ngTemplateOutlet=\"\n (customTemplatesService.voiceRecordingAttachmentTemplate$\n | async) || defaultRecording;\n context: getAttachmentContext(attachment)\n \"\n ></ng-container>\n <ng-template #defaultRecording>\n <stream-voice-recording\n data-testclass=\"voice-recording\"\n [attachment]=\"attachment\"\n ></stream-voice-recording>\n </ng-template>\n </ng-container>\n <ng-container\n *ngIf=\"\n isCard(attachment) &&\n getCardAttachmentConfiguration(attachment) as attachmentConfiguration\n \"\n >\n <ng-container\n *ngTemplateOutlet=\"\n (customTemplatesService.cardAttachmentTemplate$ | async) ||\n defaultCard;\n context: getAttachmentContext(attachment)\n \"\n ></ng-container>\n <ng-template #defaultCard let-attachmentContext=\"attachment\">\n <div\n class=\"str-chat__message-attachment-card str-chat__message-attachment-card--{{\n attachmentContext.type\n }}\"\n >\n <div\n *ngIf=\"attachmentConfiguration.url\"\n class=\"str-chat__message-attachment-card--header\"\n >\n <img\n fetchpriority=\"low\"\n loading=\"lazy\"\n data-testclass=\"card-img\"\n alt=\"{{ attachmentConfiguration.url }}\"\n src=\"{{ attachmentConfiguration.url }}\"\n [ngStyle]=\"{\n height: attachmentConfiguration.height,\n width: attachmentConfiguration.width\n }\"\n />\n </div>\n <div class=\"str-chat__message-attachment-card--content\">\n <div class=\"str-chat__message-attachment-card--flex\">\n <div\n *ngIf=\"attachmentContext.title\"\n data-testclass=\"card-title\"\n class=\"str-chat__message-attachment-card--title\"\n >\n {{ attachmentContext.title }}\n </div>\n <div\n *ngIf=\"attachmentContext.text\"\n class=\"str-chat__message-attachment-card--text\"\n data-testclass=\"card-text\"\n >\n {{ attachmentContext.text }}\n </div>\n <a\n *ngIf=\"\n attachmentContext.title_link ||\n attachmentContext.og_scrape_url\n \"\n class=\"str-chat__message-attachment-card--url\"\n data-testclass=\"url-link\"\n noopener\n noreferrer\n target=\"_blank\"\n href=\"{{\n attachmentContext.title_link ||\n attachmentContext.og_scrape_url\n }}\"\n >\n {{\n trimUrl(\n attachmentContext.title_link ||\n attachmentContext.og_scrape_url\n )\n }}\n </a>\n </div>\n </div>\n </div>\n </ng-template>\n </ng-container>\n <ng-container *ngIf=\"attachment.actions && attachment.actions.length > 0\">\n <ng-container\n *ngTemplateOutlet=\"\n (customTemplatesService.attachmentActionsTemplate$ | async) ||\n defaultActions;\n context: getAttachmentContext(attachment)\n \"\n ></ng-container>\n <ng-template #defaultActions let-attachmentContext=\"attachment\">\n <div class=\"str-chat__message-attachment-actions\">\n <div class=\"str-chat__message-attachment-actions-form\">\n <button\n *ngFor=\"\n let action of attachmentContext.actions;\n trackBy: trackByActionValue\n \"\n data-testclass=\"attachment-action\"\n class=\"str-chat__message-attachment-actions-button str-chat__message-attachment-actions-button--{{\n action.style\n }}\"\n (click)=\"sendAction(action)\"\n (keyup.enter)=\"sendAction(action)\"\n >\n {{ action.text }}\n </button>\n </div>\n </div>\n </ng-template>\n </ng-container>\n </div>\n </ng-container>\n\n <ng-container *ngIf=\"imagesToView && imagesToView.length > 0\">\n <ng-container\n *ngTemplateOutlet=\"\n (customTemplatesService.modalTemplate$ | async) || defaultModal;\n context: getModalContext()\n \"\n ></ng-container>\n </ng-container>\n</div>\n\n<ng-template\n #defaultModal\n let-isOpen=\"isOpen\"\n let-isOpenChangeHandler=\"isOpenChangeHandler\"\n let-content=\"content\"\n>\n <stream-modal\n class=\"stream-chat-angular__image-modal-host\"\n [isOpen]=\"isOpen\"\n [content]=\"content\"\n (isOpenChange)=\"isOpenChangeHandler($event)\"\n >\n </stream-modal>\n</ng-template>\n\n<ng-template #modalContent>\n <div class=\"stream-chat-angular__image-modal str-chat__image-carousel\">\n <img\n #imgElement\n class=\"stream-chat-angular__image-modal-image str-chat__image-carousel-image\"\n data-testid=\"modal-image\"\n [src]=\"\n getCarouselImageAttachmentConfiguration(\n imagesToView[imagesToViewCurrentIndex],\n imgElement\n ).url\n \"\n [style.--original-height]=\"\n getCarouselImageAttachmentConfiguration(\n imagesToView[imagesToViewCurrentIndex],\n imgElement\n ).originalHeight\n \"\n [style.--original-width]=\"\n getCarouselImageAttachmentConfiguration(\n imagesToView[imagesToViewCurrentIndex],\n imgElement\n ).originalWidth\n \"\n [alt]=\"imagesToView[imagesToViewCurrentIndex].fallback\"\n [ngStyle]=\"{\n width: getCarouselImageAttachmentConfiguration(\n imagesToView[imagesToViewCurrentIndex],\n imgElement\n ).width,\n height: getCarouselImageAttachmentConfiguration(\n imagesToView[imagesToViewCurrentIndex],\n imgElement\n ).height\n }\"\n />\n <div>\n <button\n class=\"stream-chat-angular__image-modal-stepper str-chat__image-carousel-stepper str-chat__image-carousel-stepper-prev\"\n data-testid=\"image-modal-prev\"\n type=\"button\"\n [ngStyle]=\"{\n visibility: isImageModalPrevButtonVisible ? 'visible' : 'hidden'\n }\"\n (click)=\"stepImages(-1)\"\n (keyup.enter)=\"stepImages(-1)\"\n >\n <stream-icon-placeholder icon=\"arrow-left\"></stream-icon-placeholder>\n </button>\n <button\n class=\"stream-chat-angular__image-modal-stepper str-chat__image-carousel-stepper str-chat__image-carousel-stepper-next\"\n type=\"button\"\n data-testid=\"image-modal-next\"\n [ngStyle]=\"{\n visibility: isImageModalNextButtonVisible ? 'visible' : 'hidden'\n }\"\n (click)=\"stepImages(1)\"\n (keyup.enter)=\"stepImages(1)\"\n >\n <stream-icon-placeholder icon=\"arrow-right\"></stream-icon-placeholder>\n </button>\n </div>\n </div>\n</ng-template>\n" }]
4655
4683
  }], ctorParameters: function () { return [{ type: CustomTemplatesService }, { type: ChannelService }, { type: AttachmentConfigurationService }]; }, propDecorators: { messageId: [{
4656
4684
  type: Input
4657
4685
  }], parentMessageId: [{
@@ -4667,21 +4695,159 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.4", ngImpor
4667
4695
  args: ['modalContent', { static: true }]
4668
4696
  }] } });
4669
4697
 
4698
+ /**
4699
+ * The `PaginatedListComponent` is a utility element that can display a list of any items. It uses infinite scrolls to load more elements. Providing the data to display, is the responsibility of the parent component.
4700
+ */
4701
+ class PaginatedListComponent {
4702
+ constructor(ngZone, cdRef) {
4703
+ this.ngZone = ngZone;
4704
+ this.cdRef = cdRef;
4705
+ /**
4706
+ * The items to display
4707
+ */
4708
+ this.items = [];
4709
+ /**
4710
+ * If `true`, the loading indicator will be displayed
4711
+ */
4712
+ this.isLoading = false;
4713
+ /**
4714
+ * If `false` the component won't ask for more data vua the `loadMore` output
4715
+ */
4716
+ this.hasMore = false;
4717
+ /**
4718
+ * The `trackBy` to use with the `NgFor` directive
4719
+ * @param i
4720
+ * @returns the track by id
4721
+ */
4722
+ this.trackBy = (i) => i;
4723
+ /**
4724
+ * The component will signal via this output when more items should be fetched
4725
+ *
4726
+ * The new items should be appended to the `items` array
4727
+ */
4728
+ this.loadMore = new EventEmitter();
4729
+ this.isScrollable = false;
4730
+ this.isAtBottom = false;
4731
+ }
4732
+ ngAfterViewInit() {
4733
+ this.ngZone.runOutsideAngular(() => {
4734
+ var _a, _b;
4735
+ (_b = (_a = this.scrollContainer) === null || _a === void 0 ? void 0 : _a.nativeElement) === null || _b === void 0 ? void 0 : _b.addEventListener('scroll', () => this.scrolled());
4736
+ });
4737
+ }
4738
+ scrolled() {
4739
+ if (!this.hasMore) {
4740
+ return;
4741
+ }
4742
+ const isScrollable = this.scrollContainer.nativeElement.scrollHeight >
4743
+ this.scrollContainer.nativeElement.clientHeight;
4744
+ if (this.isScrollable !== isScrollable) {
4745
+ this.ngZone.run(() => {
4746
+ this.isScrollable = isScrollable;
4747
+ this.cdRef.detectChanges();
4748
+ });
4749
+ }
4750
+ const isAtBottom = Math.ceil(this.scrollContainer.nativeElement.scrollTop) +
4751
+ this.scrollContainer.nativeElement.clientHeight +
4752
+ 1 >=
4753
+ this.scrollContainer.nativeElement.scrollHeight;
4754
+ if (this.isAtBottom !== isAtBottom) {
4755
+ this.ngZone.run(() => {
4756
+ this.isAtBottom = isAtBottom;
4757
+ if (this.isAtBottom && !this.isLoading) {
4758
+ this.loadMore.emit();
4759
+ }
4760
+ this.cdRef.detectChanges();
4761
+ });
4762
+ }
4763
+ }
4764
+ }
4765
+ PaginatedListComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.4", ngImport: i0, type: PaginatedListComponent, deps: [{ token: i0.NgZone }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
4766
+ PaginatedListComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.0.4", type: PaginatedListComponent, selector: "stream-paginated-list", inputs: { items: "items", isLoading: "isLoading", hasMore: "hasMore", trackBy: "trackBy" }, outputs: { loadMore: "loadMore" }, queries: [{ propertyName: "itemTempalteRef", first: true, predicate: TemplateRef, descendants: true }], viewQueries: [{ propertyName: "scrollContainer", first: true, predicate: ["container"], descendants: true }], ngImport: i0, template: "<div class=\"stream-chat__paginated-list\" #container>\n <div\n data-testid=\"item\"\n class=\"stream-chat__paginated-list-item\"\n *ngFor=\"let item of items; let index = index; trackBy: trackBy\"\n >\n <ng-template\n *ngIf=\"itemTempalteRef\"\n [ngTemplateOutlet]=\"itemTempalteRef\"\n [ngTemplateOutletContext]=\"{ item: item, index: index }\"\n ></ng-template>\n </div>\n <button\n *ngIf=\"hasMore && !isScrollable\"\n class=\"str-chat__load-more-button__button str-chat__cta-button\"\n data-testid=\"load-more-button\"\n [disabled]=\"isLoading\"\n (click)=\"loadMore.emit()\"\n (keyup.enter)=\"loadMore.emit()\"\n >\n <span>{{ \"Load more\" | translate }}</span>\n </button>\n <stream-loading-indicator-placeholder\n data-testid=\"loading-indicator\"\n *ngIf=\"isLoading\"\n ></stream-loading-indicator-placeholder>\n</div>\n", dependencies: [{ kind: "directive", type: i4.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i4.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: LoadingIndicatorPlaceholderComponent, selector: "stream-loading-indicator-placeholder" }, { kind: "pipe", type: i10.TranslatePipe, name: "translate" }] });
4767
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.4", ngImport: i0, type: PaginatedListComponent, decorators: [{
4768
+ type: Component,
4769
+ args: [{ selector: 'stream-paginated-list', template: "<div class=\"stream-chat__paginated-list\" #container>\n <div\n data-testid=\"item\"\n class=\"stream-chat__paginated-list-item\"\n *ngFor=\"let item of items; let index = index; trackBy: trackBy\"\n >\n <ng-template\n *ngIf=\"itemTempalteRef\"\n [ngTemplateOutlet]=\"itemTempalteRef\"\n [ngTemplateOutletContext]=\"{ item: item, index: index }\"\n ></ng-template>\n </div>\n <button\n *ngIf=\"hasMore && !isScrollable\"\n class=\"str-chat__load-more-button__button str-chat__cta-button\"\n data-testid=\"load-more-button\"\n [disabled]=\"isLoading\"\n (click)=\"loadMore.emit()\"\n (keyup.enter)=\"loadMore.emit()\"\n >\n <span>{{ \"Load more\" | translate }}</span>\n </button>\n <stream-loading-indicator-placeholder\n data-testid=\"loading-indicator\"\n *ngIf=\"isLoading\"\n ></stream-loading-indicator-placeholder>\n</div>\n" }]
4770
+ }], ctorParameters: function () { return [{ type: i0.NgZone }, { type: i0.ChangeDetectorRef }]; }, propDecorators: { items: [{
4771
+ type: Input
4772
+ }], isLoading: [{
4773
+ type: Input
4774
+ }], hasMore: [{
4775
+ type: Input
4776
+ }], trackBy: [{
4777
+ type: Input
4778
+ }], itemTempalteRef: [{
4779
+ type: ContentChild,
4780
+ args: [TemplateRef]
4781
+ }], loadMore: [{
4782
+ type: Output
4783
+ }], scrollContainer: [{
4784
+ type: ViewChild,
4785
+ args: ['container']
4786
+ }] } });
4787
+
4788
+ /**
4789
+ * The `UserListComponent` can display a list of Stream users with pagination
4790
+ */
4791
+ class UserListComponent {
4792
+ constructor() {
4793
+ /**
4794
+ * The users to display
4795
+ */
4796
+ this.users = [];
4797
+ /**
4798
+ * If `true`, the loading indicator will be displayed
4799
+ */
4800
+ this.isLoading = false;
4801
+ /**
4802
+ * If `false` the component won't ask for more data vua the `loadMore` output
4803
+ */
4804
+ this.hasMore = false;
4805
+ /**
4806
+ * The component will signal via this output when more items should be fetched
4807
+ *
4808
+ * The new items should be appended to the `items` array
4809
+ */
4810
+ this.loadMore = new EventEmitter();
4811
+ }
4812
+ trackByUserId(_, item) {
4813
+ return item.id;
4814
+ }
4815
+ }
4816
+ UserListComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.4", ngImport: i0, type: UserListComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
4817
+ UserListComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.0.4", type: UserListComponent, selector: "stream-user-list", inputs: { users: "users", isLoading: "isLoading", hasMore: "hasMore" }, outputs: { loadMore: "loadMore" }, ngImport: i0, template: "<stream-paginated-list\n [items]=\"users\"\n [hasMore]=\"hasMore\"\n (loadMore)=\"loadMore.emit()\"\n [isLoading]=\"isLoading\"\n [trackBy]=\"trackByUserId\"\n>\n <ng-template let-user=\"item\">\n <div class=\"str-chat__user-list-item\">\n <stream-avatar-placeholder\n data-testclass=\"avatar\"\n class=\"str-chat__avatar str-chat__avatar--circle\"\n type=\"user\"\n location=\"reaction\"\n [imageUrl]=\"user.image\"\n [name]=\"user.name\"\n [user]=\"user\"\n ></stream-avatar-placeholder>\n <span data-testclass=\"username\" class=\"str-chat__user-item--name\">{{\n user.name\n }}</span>\n </div>\n </ng-template>\n</stream-paginated-list>\n", dependencies: [{ kind: "component", type: AvatarPlaceholderComponent, selector: "stream-avatar-placeholder", inputs: ["name", "imageUrl", "location", "channel", "user", "type", "initialsType", "showOnlineIndicator"] }, { kind: "component", type: PaginatedListComponent, selector: "stream-paginated-list", inputs: ["items", "isLoading", "hasMore", "trackBy"], outputs: ["loadMore"] }] });
4818
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.4", ngImport: i0, type: UserListComponent, decorators: [{
4819
+ type: Component,
4820
+ args: [{ selector: 'stream-user-list', template: "<stream-paginated-list\n [items]=\"users\"\n [hasMore]=\"hasMore\"\n (loadMore)=\"loadMore.emit()\"\n [isLoading]=\"isLoading\"\n [trackBy]=\"trackByUserId\"\n>\n <ng-template let-user=\"item\">\n <div class=\"str-chat__user-list-item\">\n <stream-avatar-placeholder\n data-testclass=\"avatar\"\n class=\"str-chat__avatar str-chat__avatar--circle\"\n type=\"user\"\n location=\"reaction\"\n [imageUrl]=\"user.image\"\n [name]=\"user.name\"\n [user]=\"user\"\n ></stream-avatar-placeholder>\n <span data-testclass=\"username\" class=\"str-chat__user-item--name\">{{\n user.name\n }}</span>\n </div>\n </ng-template>\n</stream-paginated-list>\n" }]
4821
+ }], propDecorators: { users: [{
4822
+ type: Input
4823
+ }], isLoading: [{
4824
+ type: Input
4825
+ }], hasMore: [{
4826
+ type: Input
4827
+ }], loadMore: [{
4828
+ type: Output
4829
+ }] } });
4830
+
4670
4831
  /**
4671
4832
  * The `MessageReactions` component displays the reactions of a message. You can read more about [message reactions](https://getstream.io/chat/docs/javascript/send_reaction/?language=javascript) in the platform documentation.
4672
4833
  */
4673
4834
  class MessageReactionsComponent {
4674
- constructor(cdRef, channelService, messageReactionsService, customTemplatesService) {
4835
+ constructor(cdRef, messageReactionsService, customTemplatesService) {
4675
4836
  this.cdRef = cdRef;
4676
- this.channelService = channelService;
4677
4837
  this.messageReactionsService = messageReactionsService;
4678
4838
  this.customTemplatesService = customTemplatesService;
4679
4839
  /**
4680
4840
  * The number of reactions grouped by [reaction types](https://github.com/GetStream/stream-chat-angular/tree/master/projects/stream-chat-angular/src/lib/message-reactions/message-reactions.component.ts)
4681
4841
  */
4842
+ this.messageReactionGroups = undefined;
4843
+ /**
4844
+ * The number of reactions grouped by [reaction types](https://github.com/GetStream/stream-chat-angular/tree/master/projects/stream-chat-angular/src/lib/message-reactions/message-reactions.component.ts)
4845
+ * @deprecated use `messageReactionGroups`
4846
+ */
4682
4847
  this.messageReactionCounts = {};
4683
4848
  /**
4684
4849
  * List of reactions of a [message](../types/stream-message.mdx), used to display the users of a reaction type.
4850
+ * @deprecated you can fetch the reactions using [`messageReactionsService.queryReactions()`](https://getstream.io/chat/docs/sdk/angular/services/MessageReactionsService/#queryreactions)
4685
4851
  */
4686
4852
  this.latestReactions = [];
4687
4853
  /**
@@ -4692,12 +4858,15 @@ class MessageReactionsComponent {
4692
4858
  this.reactions = [];
4693
4859
  this.shouldHandleReactionClick = true;
4694
4860
  this.existingReactions = [];
4695
- this.reactionsCount = 0;
4696
4861
  this.reactionOptions = [];
4862
+ this.usersByReactions = {};
4697
4863
  this.subscriptions = [];
4698
4864
  this.isViewInited = false;
4699
4865
  this.isOpenChange = (isOpen) => {
4700
4866
  this.selectedReactionType = isOpen ? this.selectedReactionType : undefined;
4867
+ if (!isOpen) {
4868
+ this.usersByReactions = {};
4869
+ }
4701
4870
  };
4702
4871
  }
4703
4872
  ngOnInit() {
@@ -4710,15 +4879,21 @@ class MessageReactionsComponent {
4710
4879
  }));
4711
4880
  }
4712
4881
  ngOnChanges(changes) {
4713
- if (changes.messageReactionCounts) {
4882
+ if (changes.messageReactionCounts || changes.messageReactionGroups) {
4883
+ if (this.messageReactionCounts && !this.messageReactionGroups) {
4884
+ this.messageReactionGroups = {};
4885
+ Object.keys(this.messageReactionCounts).forEach((k) => {
4886
+ var _a, _b, _c, _d;
4887
+ this.messageReactionGroups[k] = {
4888
+ count: (_b = (_a = this.messageReactionCounts) === null || _a === void 0 ? void 0 : _a[k]) !== null && _b !== void 0 ? _b : 0,
4889
+ sum_scores: (_d = (_c = this.messageReactionCounts) === null || _c === void 0 ? void 0 : _c[k]) !== null && _d !== void 0 ? _d : 0,
4890
+ first_reaction_at: undefined,
4891
+ last_reaction_at: undefined,
4892
+ };
4893
+ });
4894
+ }
4714
4895
  this.setExistingReactions();
4715
4896
  }
4716
- if (changes.messageReactionCounts && this.messageReactionCounts) {
4717
- const reactionsCount = Object.keys(this.messageReactionCounts).reduce((acc, key) => acc + (this.messageReactionCounts[key] || 0), 0);
4718
- this.shouldHandleReactionClick =
4719
- reactionsCount <= ChannelService.MAX_MESSAGE_REACTIONS_TO_FETCH ||
4720
- !!this.messageReactionsService.customReactionClickHandler;
4721
- }
4722
4897
  }
4723
4898
  ngAfterViewInit() {
4724
4899
  this.isViewInited = true;
@@ -4730,100 +4905,84 @@ class MessageReactionsComponent {
4730
4905
  return this.messageReactionsService.reactions[reactionType];
4731
4906
  }
4732
4907
  reactionSelected(reactionType) {
4733
- if (!this.shouldHandleReactionClick) {
4734
- return;
4735
- }
4736
- if (!this.messageId) {
4737
- return;
4738
- }
4739
- if (this.messageReactionsService.customReactionClickHandler) {
4740
- this.messageReactionsService.customReactionClickHandler({
4741
- messageId: this.messageId,
4742
- reactionType: reactionType,
4743
- });
4744
- }
4745
- else {
4746
- this.selectedReactionType = reactionType;
4747
- void this.fetchAllReactions();
4748
- }
4749
- }
4750
- getUsersByReaction(reactionType) {
4751
- return this.latestReactions
4752
- .filter((r) => r.type === reactionType)
4753
- .map((r) => { var _a, _b; return ((_a = r.user) === null || _a === void 0 ? void 0 : _a.name) || ((_b = r.user) === null || _b === void 0 ? void 0 : _b.id); })
4754
- .filter((i) => !!i)
4755
- .join(', ');
4756
- }
4757
- getAllUsersByReaction(reactionType) {
4758
- if (!reactionType) {
4759
- return [];
4760
- }
4761
- const users = this.reactions
4762
- .filter((r) => r.type === reactionType)
4763
- .map((r) => r.user)
4764
- .filter((i) => !!i);
4765
- users.sort((u1, u2) => {
4766
- var _a, _b;
4767
- const name1 = (_a = u1.name) === null || _a === void 0 ? void 0 : _a.toLowerCase();
4768
- const name2 = (_b = u2.name) === null || _b === void 0 ? void 0 : _b.toLowerCase();
4769
- if (!name1) {
4770
- return 1;
4771
- }
4772
- if (!name2) {
4773
- return -1;
4774
- }
4775
- if (name1 === name2) {
4776
- return 0;
4908
+ return __awaiter(this, void 0, void 0, function* () {
4909
+ if (!this.messageId) {
4910
+ return;
4777
4911
  }
4778
- if (name1 < name2) {
4779
- return -1;
4912
+ if (this.messageReactionsService.customReactionClickHandler) {
4913
+ this.messageReactionsService.customReactionClickHandler({
4914
+ messageId: this.messageId,
4915
+ reactionType: reactionType,
4916
+ });
4780
4917
  }
4781
4918
  else {
4782
- return 1;
4919
+ this.selectedReactionType = reactionType;
4920
+ if (!this.usersByReactions[this.selectedReactionType]) {
4921
+ this.usersByReactions[this.selectedReactionType] = {
4922
+ users: [],
4923
+ };
4924
+ yield this.loadNextPageOfReactions();
4925
+ }
4783
4926
  }
4784
4927
  });
4785
- return users;
4786
- }
4787
- trackByMessageReaction(_, item) {
4788
- return item;
4789
- }
4790
- trackByUserId(_, item) {
4791
- return item.id;
4792
- }
4793
- isOwnReaction(reactionType) {
4794
- return !!this.ownReactions.find((r) => r.type === reactionType);
4795
4928
  }
4796
- fetchAllReactions() {
4929
+ loadNextPageOfReactions() {
4797
4930
  return __awaiter(this, void 0, void 0, function* () {
4798
- if (!this.messageId) {
4931
+ if (!this.messageId || !this.selectedReactionType) {
4799
4932
  return;
4800
4933
  }
4801
4934
  this.isLoading = true;
4802
4935
  try {
4803
- this.reactions = yield this.channelService.getMessageReactions(this.messageId);
4936
+ const response = yield this.messageReactionsService.queryReactions(this.messageId, this.selectedReactionType, this.usersByReactions[this.selectedReactionType].next);
4937
+ this.usersByReactions[this.selectedReactionType].users = [
4938
+ ...this.usersByReactions[this.selectedReactionType].users,
4939
+ ...response.reactions
4940
+ .map((r) => r.user)
4941
+ .filter((u) => !!u),
4942
+ ];
4943
+ this.usersByReactions[this.selectedReactionType].next = response.next;
4804
4944
  }
4805
- catch (error) {
4945
+ catch (_) {
4806
4946
  this.selectedReactionType = undefined;
4807
4947
  }
4808
4948
  finally {
4809
4949
  this.isLoading = false;
4950
+ }
4951
+ if (this.isViewInited) {
4810
4952
  this.cdRef.detectChanges();
4811
4953
  }
4812
4954
  });
4813
4955
  }
4956
+ trackByMessageReaction(_, item) {
4957
+ return item;
4958
+ }
4959
+ isOwnReaction(reactionType) {
4960
+ return !!this.ownReactions.find((r) => r.type === reactionType);
4961
+ }
4814
4962
  setExistingReactions() {
4815
- this.existingReactions = Object.keys(this.messageReactionCounts)
4963
+ var _a;
4964
+ this.existingReactions = Object.keys((_a = this.messageReactionGroups) !== null && _a !== void 0 ? _a : {})
4816
4965
  .filter((k) => this.reactionOptions.indexOf(k) !== -1)
4817
- .filter((k) => this.messageReactionCounts[k] > 0);
4818
- this.reactionsCount = this.existingReactions.reduce((total, reaction) => total + this.messageReactionCounts[reaction], 0);
4966
+ .filter((k) => this.messageReactionGroups[k].count > 0)
4967
+ .sort((r1, r2) => {
4968
+ const date1 = this.messageReactionGroups[r1].first_reaction_at
4969
+ ? new Date(this.messageReactionGroups[r1].first_reaction_at)
4970
+ : new Date();
4971
+ const date2 = this.messageReactionGroups[r2].first_reaction_at
4972
+ ? new Date(this.messageReactionGroups[r2].first_reaction_at)
4973
+ : new Date();
4974
+ return date1.getTime() - date2.getTime();
4975
+ });
4819
4976
  }
4820
4977
  }
4821
- MessageReactionsComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.4", ngImport: i0, type: MessageReactionsComponent, deps: [{ token: i0.ChangeDetectorRef }, { token: ChannelService }, { token: MessageReactionsService }, { token: CustomTemplatesService }], target: i0.ɵɵFactoryTarget.Component });
4822
- MessageReactionsComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.0.4", type: MessageReactionsComponent, selector: "stream-message-reactions", inputs: { messageId: "messageId", messageReactionCounts: "messageReactionCounts", latestReactions: "latestReactions", ownReactions: "ownReactions" }, viewQueries: [{ propertyName: "selectorContainer", first: true, predicate: ["selectorContainer"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div\n *ngIf=\"existingReactions.length > 0\"\n data-testid=\"reaction-list\"\n class=\"str-chat__reaction-list str-chat__message-reactions-container\"\n [class.str-chat__reaction-list--reverse]=\"true\"\n>\n <ul class=\"str-chat__message-reactions\">\n <li\n *ngFor=\"\n let reactionType of existingReactions;\n trackBy: trackByMessageReaction\n \"\n class=\"str-chat__message-reaction\"\n data-testclass=\"emoji\"\n [ngStyle]=\"{ cursor: shouldHandleReactionClick ? 'pointer' : 'default' }\"\n [class.str-chat__message-reaction-own]=\"isOwnReaction(reactionType)\"\n (click)=\"reactionSelected(reactionType)\"\n (keyup.enter)=\"reactionSelected(reactionType)\"\n >\n <span class=\"emoji str-chat__message-reaction-emoji\">\n {{ getEmojiByReaction(reactionType) }}&nbsp;\n </span>\n <span\n data-testclass=\"reaction-list-reaction-count\"\n class=\"str-chat__message-reaction-count\"\n >\n {{ messageReactionCounts[reactionType] }}\n </span>\n </li>\n <li>\n <span\n data-testid=\"reactions-count\"\n class=\"str-chat__reaction-list--counter\"\n >{{ reactionsCount }}</span\n >\n </li>\n </ul>\n</div>\n\n<ng-container *ngIf=\"selectedReactionType\">\n <ng-container\n *ngTemplateOutlet=\"\n (customTemplatesService.modalTemplate$ | async) || defaultModal;\n context: {\n isOpen: !!selectedReactionType,\n messageId: messageId,\n reactionType: selectedReactionType,\n isOpenChangeHandler: isOpenChange,\n content: modalContent\n }\n \"\n ></ng-container>\n</ng-container>\n\n<ng-template\n #defaultModal\n let-isOpen=\"isOpen\"\n let-messageId=\"messageId\"\n let-reactionType=\"reactionType\"\n let-isOpenChangeHandler=\"isOpenChangeHandler\"\n let-content=\"content\"\n>\n <stream-modal\n class=\"str-chat__message-reactions-details-modal\"\n [isOpen]=\"isOpen\"\n [content]=\"content\"\n (isOpenChange)=\"isOpenChangeHandler($event)\"\n >\n </stream-modal>\n</ng-template>\n\n<ng-template #modalContent>\n <div class=\"str-chat__message-reactions-details\">\n <div class=\"str-chat__message-reactions-details-reaction-types\">\n <div\n *ngFor=\"\n let reactionType of existingReactions;\n trackBy: trackByMessageReaction\n \"\n class=\"str-chat__message-reactions-details-reaction-type\"\n [ngStyle]=\"{\n cursor: shouldHandleReactionClick ? 'pointer' : 'default'\n }\"\n attr.data-testid=\"reaction-details-selector-{{ reactionType }}\"\n [class.str-chat__message-reactions-details-reaction-type--selected]=\"\n reactionType === selectedReactionType\n \"\n (click)=\"selectedReactionType = reactionType; allUsers.scrollTop = 0\"\n (keyup.enter)=\"\n selectedReactionType = reactionType; allUsers.scrollTop = 0\n \"\n >\n <span class=\"emoji str-chat__message-reaction-emoji\">\n {{ getEmojiByReaction(reactionType) }}&nbsp;\n </span>\n <span class=\"str-chat__message-reaction-count\">\n {{ messageReactionCounts[reactionType] }}\n </span>\n </div>\n </div>\n <div\n class=\"\n emoji\n str-chat__message-reaction-emoji str-chat__message-reaction-emoji-big\n \"\n >\n {{ getEmojiByReaction(selectedReactionType!) }}\n </div>\n <div\n #allUsers\n data-testid=\"all-reacting-users\"\n class=\"str-chat__message-reactions-details-reacting-users\"\n >\n <stream-loading-indicator\n *ngIf=\"isLoading; else reactions\"\n ></stream-loading-indicator>\n <ng-template #reactions>\n <div\n *ngFor=\"\n let user of getAllUsersByReaction(selectedReactionType);\n trackBy: trackByUserId\n \"\n class=\"str-chat__message-reactions-details-reacting-user\"\n >\n <stream-avatar-placeholder\n data-testclass=\"avatar\"\n class=\"str-chat__avatar str-chat__avatar--circle\"\n type=\"user\"\n location=\"reaction\"\n [imageUrl]=\"user.image\"\n [name]=\"user.name\"\n [user]=\"user\"\n ></stream-avatar-placeholder>\n <span\n data-testclass=\"reaction-user-username\"\n class=\"str-chat__user-item--name\"\n >{{ user.name }}</span\n >\n </div>\n </ng-template>\n </div>\n </div>\n</ng-template>\n", dependencies: [{ kind: "directive", type: i4.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i4.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i4.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "component", type: AvatarPlaceholderComponent, selector: "stream-avatar-placeholder", inputs: ["name", "imageUrl", "location", "channel", "user", "type", "initialsType", "showOnlineIndicator"] }, { kind: "component", type: LoadingIndicatorComponent, selector: "stream-loading-indicator" }, { kind: "component", type: ModalComponent, selector: "stream-modal", inputs: ["isOpen", "content"], outputs: ["isOpenChange"] }, { kind: "pipe", type: i4.AsyncPipe, name: "async" }] });
4978
+ MessageReactionsComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.4", ngImport: i0, type: MessageReactionsComponent, deps: [{ token: i0.ChangeDetectorRef }, { token: MessageReactionsService }, { token: CustomTemplatesService }], target: i0.ɵɵFactoryTarget.Component });
4979
+ MessageReactionsComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.0.4", type: MessageReactionsComponent, selector: "stream-message-reactions", inputs: { messageId: "messageId", messageReactionGroups: "messageReactionGroups", messageReactionCounts: "messageReactionCounts", latestReactions: "latestReactions", ownReactions: "ownReactions" }, viewQueries: [{ propertyName: "selectorContainer", first: true, predicate: ["selectorContainer"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div\n *ngIf=\"existingReactions.length > 0\"\n data-testid=\"reaction-list\"\n class=\"str-chat__reaction-list str-chat__message-reactions-container\"\n [class.str-chat__reaction-list--reverse]=\"true\"\n>\n <ul class=\"str-chat__message-reactions\">\n <li\n *ngFor=\"\n let reactionType of existingReactions;\n trackBy: trackByMessageReaction\n \"\n class=\"str-chat__message-reaction\"\n data-testclass=\"emoji\"\n [class.str-chat__message-reaction-own]=\"isOwnReaction(reactionType)\"\n (click)=\"reactionSelected(reactionType)\"\n (keyup.enter)=\"reactionSelected(reactionType)\"\n >\n <span class=\"emoji str-chat__message-reaction-emoji\">\n {{ getEmojiByReaction(reactionType) }}&nbsp;\n </span>\n <span\n data-testclass=\"reaction-list-reaction-count\"\n class=\"str-chat__message-reaction-count\"\n >\n {{ messageReactionGroups?.[reactionType]?.count ?? 0 }}\n </span>\n </li>\n </ul>\n</div>\n\n<ng-container *ngIf=\"selectedReactionType\">\n <ng-container\n *ngTemplateOutlet=\"\n (customTemplatesService.modalTemplate$ | async) || defaultModal;\n context: {\n isOpen: !!selectedReactionType,\n messageId: messageId,\n reactionType: selectedReactionType,\n isOpenChangeHandler: isOpenChange,\n content: modalContent\n }\n \"\n ></ng-container>\n</ng-container>\n\n<ng-template\n #defaultModal\n let-isOpen=\"isOpen\"\n let-messageId=\"messageId\"\n let-reactionType=\"reactionType\"\n let-isOpenChangeHandler=\"isOpenChangeHandler\"\n let-content=\"content\"\n>\n <stream-modal\n class=\"str-chat__message-reactions-details-modal\"\n [isOpen]=\"isOpen\"\n [content]=\"content\"\n (isOpenChange)=\"isOpenChangeHandler($event)\"\n >\n </stream-modal>\n</ng-template>\n\n<ng-template #modalContent>\n <div class=\"str-chat__message-reactions-details\">\n <div class=\"str-chat__message-reactions-details-reaction-types\">\n <div\n *ngFor=\"\n let reactionType of existingReactions;\n trackBy: trackByMessageReaction\n \"\n class=\"str-chat__message-reactions-details-reaction-type\"\n attr.data-testid=\"reaction-details-selector-{{ reactionType }}\"\n [class.str-chat__message-reactions-details-reaction-type--selected]=\"\n reactionType === selectedReactionType\n \"\n (click)=\"reactionSelected(reactionType)\"\n (keyup.enter)=\"reactionSelected(reactionType)\"\n >\n <span class=\"emoji str-chat__message-reaction-emoji\">\n {{ getEmojiByReaction(reactionType) }}&nbsp;\n </span>\n <span class=\"str-chat__message-reaction-count\">\n {{ messageReactionGroups?.[reactionType]?.count ?? 0 }}\n </span>\n </div>\n </div>\n <div\n class=\"emoji str-chat__message-reaction-emoji str-chat__message-reaction-emoji-big\"\n >\n {{ getEmojiByReaction(selectedReactionType!) }}\n </div>\n <div\n data-testid=\"all-reacting-users\"\n class=\"str-chat__message-reactions-details-reacting-users\"\n >\n <ng-container\n *ngFor=\"\n let reactionType of existingReactions;\n trackBy: trackByMessageReaction\n \"\n >\n <stream-user-list\n attr.data-testid=\"{{ reactionType }}-user-list\"\n [style.display]=\"\n selectedReactionType === reactionType ? 'block' : 'none'\n \"\n [users]=\"usersByReactions[reactionType]?.users || []\"\n [isLoading]=\"isLoading\"\n [hasMore]=\"!!usersByReactions[reactionType]?.next || false\"\n (loadMore)=\"loadNextPageOfReactions()\"\n ></stream-user-list>\n </ng-container>\n </div>\n </div>\n</ng-template>\n", dependencies: [{ kind: "directive", type: i4.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i4.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: ModalComponent, selector: "stream-modal", inputs: ["isOpen", "content"], outputs: ["isOpenChange"] }, { kind: "component", type: UserListComponent, selector: "stream-user-list", inputs: ["users", "isLoading", "hasMore"], outputs: ["loadMore"] }, { kind: "pipe", type: i4.AsyncPipe, name: "async" }] });
4823
4980
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.4", ngImport: i0, type: MessageReactionsComponent, decorators: [{
4824
4981
  type: Component,
4825
- args: [{ selector: 'stream-message-reactions', template: "<div\n *ngIf=\"existingReactions.length > 0\"\n data-testid=\"reaction-list\"\n class=\"str-chat__reaction-list str-chat__message-reactions-container\"\n [class.str-chat__reaction-list--reverse]=\"true\"\n>\n <ul class=\"str-chat__message-reactions\">\n <li\n *ngFor=\"\n let reactionType of existingReactions;\n trackBy: trackByMessageReaction\n \"\n class=\"str-chat__message-reaction\"\n data-testclass=\"emoji\"\n [ngStyle]=\"{ cursor: shouldHandleReactionClick ? 'pointer' : 'default' }\"\n [class.str-chat__message-reaction-own]=\"isOwnReaction(reactionType)\"\n (click)=\"reactionSelected(reactionType)\"\n (keyup.enter)=\"reactionSelected(reactionType)\"\n >\n <span class=\"emoji str-chat__message-reaction-emoji\">\n {{ getEmojiByReaction(reactionType) }}&nbsp;\n </span>\n <span\n data-testclass=\"reaction-list-reaction-count\"\n class=\"str-chat__message-reaction-count\"\n >\n {{ messageReactionCounts[reactionType] }}\n </span>\n </li>\n <li>\n <span\n data-testid=\"reactions-count\"\n class=\"str-chat__reaction-list--counter\"\n >{{ reactionsCount }}</span\n >\n </li>\n </ul>\n</div>\n\n<ng-container *ngIf=\"selectedReactionType\">\n <ng-container\n *ngTemplateOutlet=\"\n (customTemplatesService.modalTemplate$ | async) || defaultModal;\n context: {\n isOpen: !!selectedReactionType,\n messageId: messageId,\n reactionType: selectedReactionType,\n isOpenChangeHandler: isOpenChange,\n content: modalContent\n }\n \"\n ></ng-container>\n</ng-container>\n\n<ng-template\n #defaultModal\n let-isOpen=\"isOpen\"\n let-messageId=\"messageId\"\n let-reactionType=\"reactionType\"\n let-isOpenChangeHandler=\"isOpenChangeHandler\"\n let-content=\"content\"\n>\n <stream-modal\n class=\"str-chat__message-reactions-details-modal\"\n [isOpen]=\"isOpen\"\n [content]=\"content\"\n (isOpenChange)=\"isOpenChangeHandler($event)\"\n >\n </stream-modal>\n</ng-template>\n\n<ng-template #modalContent>\n <div class=\"str-chat__message-reactions-details\">\n <div class=\"str-chat__message-reactions-details-reaction-types\">\n <div\n *ngFor=\"\n let reactionType of existingReactions;\n trackBy: trackByMessageReaction\n \"\n class=\"str-chat__message-reactions-details-reaction-type\"\n [ngStyle]=\"{\n cursor: shouldHandleReactionClick ? 'pointer' : 'default'\n }\"\n attr.data-testid=\"reaction-details-selector-{{ reactionType }}\"\n [class.str-chat__message-reactions-details-reaction-type--selected]=\"\n reactionType === selectedReactionType\n \"\n (click)=\"selectedReactionType = reactionType; allUsers.scrollTop = 0\"\n (keyup.enter)=\"\n selectedReactionType = reactionType; allUsers.scrollTop = 0\n \"\n >\n <span class=\"emoji str-chat__message-reaction-emoji\">\n {{ getEmojiByReaction(reactionType) }}&nbsp;\n </span>\n <span class=\"str-chat__message-reaction-count\">\n {{ messageReactionCounts[reactionType] }}\n </span>\n </div>\n </div>\n <div\n class=\"\n emoji\n str-chat__message-reaction-emoji str-chat__message-reaction-emoji-big\n \"\n >\n {{ getEmojiByReaction(selectedReactionType!) }}\n </div>\n <div\n #allUsers\n data-testid=\"all-reacting-users\"\n class=\"str-chat__message-reactions-details-reacting-users\"\n >\n <stream-loading-indicator\n *ngIf=\"isLoading; else reactions\"\n ></stream-loading-indicator>\n <ng-template #reactions>\n <div\n *ngFor=\"\n let user of getAllUsersByReaction(selectedReactionType);\n trackBy: trackByUserId\n \"\n class=\"str-chat__message-reactions-details-reacting-user\"\n >\n <stream-avatar-placeholder\n data-testclass=\"avatar\"\n class=\"str-chat__avatar str-chat__avatar--circle\"\n type=\"user\"\n location=\"reaction\"\n [imageUrl]=\"user.image\"\n [name]=\"user.name\"\n [user]=\"user\"\n ></stream-avatar-placeholder>\n <span\n data-testclass=\"reaction-user-username\"\n class=\"str-chat__user-item--name\"\n >{{ user.name }}</span\n >\n </div>\n </ng-template>\n </div>\n </div>\n</ng-template>\n" }]
4826
- }], ctorParameters: function () { return [{ type: i0.ChangeDetectorRef }, { type: ChannelService }, { type: MessageReactionsService }, { type: CustomTemplatesService }]; }, propDecorators: { messageId: [{
4982
+ args: [{ selector: 'stream-message-reactions', template: "<div\n *ngIf=\"existingReactions.length > 0\"\n data-testid=\"reaction-list\"\n class=\"str-chat__reaction-list str-chat__message-reactions-container\"\n [class.str-chat__reaction-list--reverse]=\"true\"\n>\n <ul class=\"str-chat__message-reactions\">\n <li\n *ngFor=\"\n let reactionType of existingReactions;\n trackBy: trackByMessageReaction\n \"\n class=\"str-chat__message-reaction\"\n data-testclass=\"emoji\"\n [class.str-chat__message-reaction-own]=\"isOwnReaction(reactionType)\"\n (click)=\"reactionSelected(reactionType)\"\n (keyup.enter)=\"reactionSelected(reactionType)\"\n >\n <span class=\"emoji str-chat__message-reaction-emoji\">\n {{ getEmojiByReaction(reactionType) }}&nbsp;\n </span>\n <span\n data-testclass=\"reaction-list-reaction-count\"\n class=\"str-chat__message-reaction-count\"\n >\n {{ messageReactionGroups?.[reactionType]?.count ?? 0 }}\n </span>\n </li>\n </ul>\n</div>\n\n<ng-container *ngIf=\"selectedReactionType\">\n <ng-container\n *ngTemplateOutlet=\"\n (customTemplatesService.modalTemplate$ | async) || defaultModal;\n context: {\n isOpen: !!selectedReactionType,\n messageId: messageId,\n reactionType: selectedReactionType,\n isOpenChangeHandler: isOpenChange,\n content: modalContent\n }\n \"\n ></ng-container>\n</ng-container>\n\n<ng-template\n #defaultModal\n let-isOpen=\"isOpen\"\n let-messageId=\"messageId\"\n let-reactionType=\"reactionType\"\n let-isOpenChangeHandler=\"isOpenChangeHandler\"\n let-content=\"content\"\n>\n <stream-modal\n class=\"str-chat__message-reactions-details-modal\"\n [isOpen]=\"isOpen\"\n [content]=\"content\"\n (isOpenChange)=\"isOpenChangeHandler($event)\"\n >\n </stream-modal>\n</ng-template>\n\n<ng-template #modalContent>\n <div class=\"str-chat__message-reactions-details\">\n <div class=\"str-chat__message-reactions-details-reaction-types\">\n <div\n *ngFor=\"\n let reactionType of existingReactions;\n trackBy: trackByMessageReaction\n \"\n class=\"str-chat__message-reactions-details-reaction-type\"\n attr.data-testid=\"reaction-details-selector-{{ reactionType }}\"\n [class.str-chat__message-reactions-details-reaction-type--selected]=\"\n reactionType === selectedReactionType\n \"\n (click)=\"reactionSelected(reactionType)\"\n (keyup.enter)=\"reactionSelected(reactionType)\"\n >\n <span class=\"emoji str-chat__message-reaction-emoji\">\n {{ getEmojiByReaction(reactionType) }}&nbsp;\n </span>\n <span class=\"str-chat__message-reaction-count\">\n {{ messageReactionGroups?.[reactionType]?.count ?? 0 }}\n </span>\n </div>\n </div>\n <div\n class=\"emoji str-chat__message-reaction-emoji str-chat__message-reaction-emoji-big\"\n >\n {{ getEmojiByReaction(selectedReactionType!) }}\n </div>\n <div\n data-testid=\"all-reacting-users\"\n class=\"str-chat__message-reactions-details-reacting-users\"\n >\n <ng-container\n *ngFor=\"\n let reactionType of existingReactions;\n trackBy: trackByMessageReaction\n \"\n >\n <stream-user-list\n attr.data-testid=\"{{ reactionType }}-user-list\"\n [style.display]=\"\n selectedReactionType === reactionType ? 'block' : 'none'\n \"\n [users]=\"usersByReactions[reactionType]?.users || []\"\n [isLoading]=\"isLoading\"\n [hasMore]=\"!!usersByReactions[reactionType]?.next || false\"\n (loadMore)=\"loadNextPageOfReactions()\"\n ></stream-user-list>\n </ng-container>\n </div>\n </div>\n</ng-template>\n" }]
4983
+ }], ctorParameters: function () { return [{ type: i0.ChangeDetectorRef }, { type: MessageReactionsService }, { type: CustomTemplatesService }]; }, propDecorators: { messageId: [{
4984
+ type: Input
4985
+ }], messageReactionGroups: [{
4827
4986
  type: Input
4828
4987
  }], messageReactionCounts: [{
4829
4988
  type: Input
@@ -4963,8 +5122,8 @@ class MessageComponent {
4963
5122
  this.hasAttachment =
4964
5123
  !!((_d = this.message) === null || _d === void 0 ? void 0 : _d.attachments) && !!this.message.attachments.length;
4965
5124
  this.hasReactions =
4966
- !!((_e = this.message) === null || _e === void 0 ? void 0 : _e.reaction_counts) &&
4967
- Object.keys(this.message.reaction_counts).length > 0;
5125
+ !!((_e = this.message) === null || _e === void 0 ? void 0 : _e.reaction_groups) &&
5126
+ Object.keys(this.message.reaction_groups).length > 0;
4968
5127
  this.replyCountParam = { replyCount: (_f = this.message) === null || _f === void 0 ? void 0 : _f.reply_count };
4969
5128
  }
4970
5129
  if (changes.enabledMessageActions) {
@@ -5100,12 +5259,13 @@ class MessageComponent {
5100
5259
  };
5101
5260
  }
5102
5261
  getMessageReactionsContext() {
5103
- var _a, _b, _c, _d;
5262
+ var _a, _b, _c, _d, _e;
5104
5263
  return {
5105
5264
  messageReactionCounts: ((_a = this.message) === null || _a === void 0 ? void 0 : _a.reaction_counts) || {},
5106
5265
  latestReactions: ((_b = this.message) === null || _b === void 0 ? void 0 : _b.latest_reactions) || [],
5107
5266
  messageId: (_c = this.message) === null || _c === void 0 ? void 0 : _c.id,
5108
5267
  ownReactions: ((_d = this.message) === null || _d === void 0 ? void 0 : _d.own_reactions) || [],
5268
+ messageReactionGroups: ((_e = this.message) === null || _e === void 0 ? void 0 : _e.reaction_groups) || {},
5109
5269
  };
5110
5270
  }
5111
5271
  messageClicked() {
@@ -5290,6 +5450,12 @@ class MessageComponent {
5290
5450
  }
5291
5451
  else {
5292
5452
  this.shouldPreventMessageMenuClose = !options.fromTouch;
5453
+ // Fix for iOS Safari: iOS Safari won't close the input if we open message menu
5454
+ // The virtual keyboard can hide parts of the message menu, so we close the input here
5455
+ if (document.activeElement &&
5456
+ typeof document.activeElement.blur !==
5457
+ 'undefined')
5458
+ document.activeElement.blur();
5293
5459
  (_b = this.messageMenuTrigger) === null || _b === void 0 ? void 0 : _b.show();
5294
5460
  }
5295
5461
  if (this.isViewInited) {
@@ -5314,10 +5480,10 @@ class MessageComponent {
5314
5480
  }
5315
5481
  }
5316
5482
  MessageComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.4", ngImport: i0, type: MessageComponent, deps: [{ token: ChatClientService }, { token: ChannelService }, { token: CustomTemplatesService }, { token: i0.ChangeDetectorRef }, { token: DateParserService }, { token: MessageService }, { token: MessageActionsService }, { token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Component });
5317
- MessageComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.0.4", type: MessageComponent, selector: "stream-message", inputs: { message: "message", enabledMessageActions: "enabledMessageActions", isLastSentMessage: "isLastSentMessage", mode: "mode", isHighlighted: "isHighlighted", scroll$: "scroll$" }, viewQueries: [{ propertyName: "messageMenuTrigger", first: true, predicate: ["messageMenuTrigger"], descendants: true }, { propertyName: "messageMenuFloat", first: true, predicate: ["messageMenuFloat"], descendants: true }, { propertyName: "messageTextElement", first: true, predicate: ["messageTextElement"], descendants: true }, { propertyName: "messageBubble", first: true, predicate: ["messageBubble"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div\n #container\n data-testid=\"message-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 }} str-chat__message-menu-{{ areMessageOptionsOpen ? 'opened' : 'closed' }}\"\n [class.str-chat__message--me]=\"isSentByCurrentUser\"\n [class.str-chat__message--other]=\"!isSentByCurrentUser\"\n [class.str-chat__message-simple--me]=\"isSentByCurrentUser\"\n [class.str-chat__message--has-attachment]=\"hasAttachment\"\n [class.str-chat__message--with-reactions]=\"hasReactions\"\n [class.str-chat__message--highlighted]=\"isHighlighted\"\n [class.str-chat__message-with-thread-link]=\"shouldDisplayThreadLink\"\n [class.str-chat__message-send-can-be-retried]=\"\n (message?.status === 'failed' && message?.errorStatusCode !== 403) ||\n (message?.type === 'error' && message?.moderation_details)\n \"\n [class.str-chat__message-with-touch-support]=\"hasTouchSupport\"\n [class.str-chat__message-without-touch-support]=\"!hasTouchSupport\"\n>\n <ng-container *ngIf=\"!message?.deleted_at; else deletedMessage\">\n <ng-container *ngIf=\"message?.type !== 'system'; else systemMessage\">\n <stream-avatar-placeholder\n data-testid=\"avatar\"\n class=\"str-chat-angular__avatar-host str-chat__message-sender-avatar\"\n type=\"user\"\n location=\"message-sender\"\n [imageUrl]=\"message?.user?.image\"\n [name]=\"message?.user?.name || message?.user?.id\"\n [user]=\"message?.user || undefined\"\n ></stream-avatar-placeholder>\n <div class=\"str-chat__message-inner\">\n <div\n *ngIf=\"!hasTouchSupport && areOptionsVisible\"\n class=\"str-chat__message-simple__actions str-chat__message-options\"\n data-testid=\"message-options\"\n [class.str-chat__message-actions-open]=\"areMessageOptionsOpen\"\n >\n <div\n #messageActionsToggle\n data-testid=\"message-actions-container\"\n class=\"\n str-chat__message-actions-container\n str-chat__message-simple__actions__action\n str-chat__message-simple__actions__action--options\n \"\n [floatUiLoose]=\"messageMenuFloat\"\n [looseTrigger]=\"\n messageActionsService.customActionClickHandler ? 'none' : 'click'\n \"\n [hideOnScroll]=\"false\"\n [hideOnClickOutside]=\"true\"\n [hideOnMouseLeave]=\"false\"\n [disableAnimation]=\"false\"\n [preventOverflow]=\"true\"\n [positionFixed]=\"true\"\n (onSHown)=\"areMessageOptionsOpen = true\"\n (onHidden)=\"areMessageOptionsOpen = false\"\n >\n <div\n *ngIf=\"visibleMessageActionsCount > 0\"\n class=\"str-chat__message-actions-box-button\"\n data-testid=\"message-options-button\"\n (click)=\"messageOptionsButtonClicked()\"\n (keyup.enter)=\"messageOptionsButtonClicked()\"\n >\n <stream-icon-placeholder\n icon=\"action\"\n class=\"str-chat__message-action-icon\"\n ></stream-icon-placeholder>\n </div>\n </div>\n </div>\n <div class=\"str-chat__message-reactions-host\">\n <ng-template\n #defaultMessageReactions\n let-messageReactionCounts=\"messageReactionCounts\"\n let-latestReactions=\"latestReactions\"\n let-messageId=\"messageId\"\n let-ownReactions=\"ownReactions\"\n >\n <stream-message-reactions\n [messageReactionCounts]=\"messageReactionCounts\"\n [latestReactions]=\"latestReactions\"\n [messageId]=\"messageId\"\n [ownReactions]=\"ownReactions\"\n ></stream-message-reactions>\n </ng-template>\n <ng-container\n *ngTemplateOutlet=\"\n (customTemplatesService.messageReactionsTemplate$ | async) ||\n defaultMessageReactions;\n context: getMessageReactionsContext()\n \"\n ></ng-container>\n </div>\n <float-ui-content #messageMenuFloat>\n <ng-template\n #defaultMessageActionsBox\n let-isMine=\"isMine\"\n let-messageInput=\"message\"\n let-enabledActions=\"enabledActions\"\n let-messageTextHtmlElement=\"messageTextHtmlElement\"\n >\n <stream-message-actions-box\n [isMine]=\"isMine\"\n [message]=\"messageInput\"\n [enabledActions]=\"enabledActions\"\n [messageTextHtmlElement]=\"messageTextHtmlElement\"\n (click)=\"messageActionsBoxClicked(messageMenuFloat)\"\n ></stream-message-actions-box>\n </ng-template>\n <ng-container>\n <ng-container\n *ngTemplateOutlet=\"\n (customTemplatesService.messageActionsBoxTemplate$ | async) ||\n defaultMessageActionsBox;\n context: getMessageActionsBoxContext()\n \"\n >\n </ng-container>\n </ng-container>\n </float-ui-content>\n <div\n class=\"str-chat__message-bubble str-chat-angular__message-bubble\"\n [class.str-chat-angular__message-bubble--attachment-modal-open]=\"\n imageAttachmentModalState === 'opened'\n \"\n data-testid=\"message-bubble\"\n [floatUiLoose]=\"messageMenuFloat\"\n #messageMenuTrigger=\"floatUiLoose\"\n #messageBubble\n looseTrigger=\"none\"\n [hideOnScroll]=\"false\"\n [hideOnClickOutside]=\"true\"\n [hideOnMouseLeave]=\"false\"\n [disableAnimation]=\"true\"\n [preventOverflow]=\"true\"\n (onShown)=\"areMessageOptionsOpen = true\"\n (onHidden)=\"areMessageOptionsOpen = false\"\n [positionFixed]=\"true\"\n >\n <ng-container *ngIf=\"hasAttachment && !message?.quoted_message\">\n <div class=\"str-chat__attachments-container\">\n <ng-container\n *ngTemplateOutlet=\"attachmentsTemplate\"\n ></ng-container>\n </div>\n </ng-container>\n <div\n *ngIf=\"message?.text || (message?.quoted_message && hasAttachment)\"\n class=\"str-chat__message-text\"\n tabindex=\"0\"\n [class.str-chat__message-text--pointer-cursor]=\"\n (message?.status === 'failed' &&\n message?.errorStatusCode !== 403) ||\n (this.message?.type === 'error' &&\n this.message?.moderation_details) ||\n message?.message_text_updated_at\n \"\n (click)=\"messageClicked()\"\n (keyup.enter)=\"messageClicked()\"\n >\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 >\n <ng-container *ngTemplateOutlet=\"quotedMessage\"></ng-container>\n <ng-container *ngIf=\"hasAttachment && message?.quoted_message\">\n <ng-container\n *ngTemplateOutlet=\"attachmentsTemplate\"\n ></ng-container>\n </ng-container>\n <div\n *ngIf=\"message?.type === 'error'\"\n data-testid=\"client-error-message\"\n class=\"\n str-chat__simple-message--error-message\n str-chat__message--error-message\n \"\n >\n <ng-container *ngIf=\"!message?.moderation_details\">{{\n \"streamChat.Error \u00B7 Unsent\" | translate\n }}</ng-container>\n </div>\n <div\n *ngIf=\"message?.status === 'failed'\"\n data-testid=\"error-message\"\n class=\"\n str-chat__simple-message--error-message\n str-chat__message--error-message\n \"\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 #messageTextElement data-testid=\"text\">\n <p>\n <ng-container *ngIf=\"messageTextParts; else defaultContent\">\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-template #defaultMention let-content=\"content\">\n <span class=\"str-chat__message-mention\">{{\n content\n }}</span>\n </ng-template>\n <ng-container\n *ngTemplateOutlet=\"\n (customTemplatesService.mentionTemplate$ | async) ||\n defaultMention;\n context: getMentionContext(part)\n \"\n ></ng-container>\n </ng-template>\n </ng-container>\n </ng-container>\n <ng-template #defaultContent>\n <ng-container *ngIf=\"displayAs === 'text'; else asHTML\">\n {{ messageText || \"\" }}\n </ng-container>\n <ng-template #asHTML\n ><span\n data-testid=\"html-content\"\n [innerHTML]=\"messageText\"\n ></span\n ></ng-template>\n </ng-template>\n </p>\n </div>\n </div>\n </div>\n <stream-icon-placeholder\n class=\"str-chat__message-error-icon\"\n icon=\"error\"\n ></stream-icon-placeholder>\n </div>\n </div>\n <ng-container\n *ngTemplateOutlet=\"replyCountButton; context: { message: message }\"\n ></ng-container>\n\n <ng-container *ngTemplateOutlet=\"messageDateAndSender\"></ng-container>\n </ng-container>\n </ng-container>\n</div>\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 <ng-container\n *ngTemplateOutlet=\"\n (customTemplatesService.systemMessageTemplate$ | async) ||\n defaultSystemMessage;\n context: getMessageContext()\n \"\n ></ng-container>\n <ng-template #defaultSystemMessage let-messageInput=\"message\">\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>{{ messageInput?.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</ng-template>\n\n<ng-template #quotedMessage>\n <div\n *ngIf=\"message?.quoted_message\"\n class=\"quoted-message str-chat__quoted-message-preview\"\n data-testid=\"quoted-message-container\"\n [class.mine]=\"isSentByCurrentUser\"\n (click)=\"\n jumpToMessage(\n (message?.quoted_message)!.id,\n message?.quoted_message?.parent_id\n )\n \"\n (keyup.enter)=\"\n jumpToMessage(\n (message?.quoted_message)!.id,\n message?.quoted_message?.parent_id\n )\n \"\n >\n <stream-avatar-placeholder\n data-testid=\"qouted-message-avatar\"\n class=\"str-chat-angular__avatar-host str-chat__message-sender-avatar\"\n type=\"user\"\n location=\"quoted-message-sender\"\n [imageUrl]=\"message?.quoted_message?.user?.image\"\n [name]=\"\n message?.quoted_message?.user?.name || message?.quoted_message?.user?.id\n \"\n [user]=\"message?.quoted_message?.user || undefined\"\n ></stream-avatar-placeholder>\n <div class=\"quoted-message-inner str-chat__quoted-message-bubble\">\n <ng-container\n *ngIf=\"\n message?.quoted_message?.attachments &&\n message?.quoted_message?.attachments?.length\n \"\n >\n <ng-template\n #defaultAttachments\n let-messageId=\"messageId\"\n let-attachments=\"attachments\"\n let-parentMessageId=\"parentMessageId\"\n let-imageModalStateChangeHandler=\"imageModalStateChangeHandler\"\n >\n <stream-attachment-list\n [messageId]=\"messageId\"\n [attachments]=\"attachments\"\n [parentMessageId]=\"parentMessageId\"\n (imageModalStateChange)=\"imageModalStateChangeHandler($event)\"\n ></stream-attachment-list>\n </ng-template>\n <ng-container\n *ngTemplateOutlet=\"\n (customTemplatesService.attachmentListTemplate$ | async) ||\n defaultAttachments;\n context: getQuotedMessageAttachmentListContext()\n \"\n ></ng-container>\n </ng-container>\n <div\n data-testid=\"quoted-message-text\"\n [innerHTML]=\"\n message?.quoted_message?.translation ||\n message?.quoted_message?.html ||\n message?.quoted_message?.text\n \"\n ></div>\n </div>\n </div>\n</ng-template>\n\n<ng-template #messageDateAndSender>\n <ng-container>\n <div\n *ngIf=\"shouldDisplayTranslationNotice\"\n class=\"str-chat__translation-notice\"\n data-testid=\"translation-notice\"\n >\n <button\n *ngIf=\"displayedMessageTextContent === 'translation'\"\n data-testid=\"see-original\"\n translate\n (click)=\"displayOriginalMessage()\"\n (keyup.enter)=\"displayOriginalMessage()\"\n >\n streamChat.See original (automatically translated)\n </button>\n <button\n *ngIf=\"displayedMessageTextContent === 'original'\"\n data-testid=\"see-translation\"\n translate\n (click)=\"displayTranslatedMessage()\"\n (keyup.enter)=\"displayTranslatedMessage()\"\n >\n streamChat.See translation\n </button>\n </div>\n <ng-container\n *ngIf=\"customTemplatesService.customMessageMetadataTemplate$ | async\"\n >\n <div class=\"str-chat__custom-message-metadata\">\n <ng-container\n *ngTemplateOutlet=\"\n (customTemplatesService.customMessageMetadataTemplate$ | async)!;\n context: getMessageMetadataContext()\n \"\n ></ng-container>\n </div>\n </ng-container>\n <div\n class=\"\n str-chat__message-data\n str-chat__message-simple-data\n str-chat__message-metadata\n \"\n >\n <ng-container *ngTemplateOutlet=\"messageStatus\"></ng-container>\n\n <span\n *ngIf=\"!isSentByCurrentUser\"\n data-testid=\"sender\"\n class=\"str-chat__message-simple-name str-chat__message-sender-name\"\n >\n {{ message?.user?.name ? message?.user?.name : message?.user?.id }}\n </span>\n <span\n data-testid=\"date\"\n class=\"str-chat__message-simple-timestamp str-chat__message-simple-time\"\n >\n {{ parsedDate }}\n </span>\n <ng-container *ngIf=\"message?.message_text_updated_at\">\n <span\n data-testid=\"edited-flag\"\n class=\"str-chat__mesage-simple-edited\"\n translate\n >streamChat.Edited</span\n >\n <div\n data-testid=\"edited-timestamp\"\n class=\"str-chat__message-edited-timestamp\"\n [ngClass]=\"{\n 'str-chat__message-edited-timestamp--open': isEditedFlagOpened,\n 'str-chat__message-edited-timestamp--collapsed': !isEditedFlagOpened\n }\"\n >\n <span translate>streamChat.Edited</span>\n <time\n dateTime=\"{{ message?.message_text_updated_at }}\"\n title=\"{{ message?.message_text_updated_at }}\"\n >\n {{ pasedEditedDate }}\n </time>\n </div>\n </ng-container>\n </div>\n </ng-container>\n</ng-template>\n\n<ng-template #messageStatus>\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' && isMessageDeliveredAndRead && canDisplayReadStatus;\n else deliveredStatus\n \"\n >\n <ng-container *ngTemplateOutlet=\"readStatus\"></ng-container>\n </ng-container>\n </ng-template>\n <ng-template #deliveredStatus>\n <ng-container\n *ngTemplateOutlet=\"\n (customTemplatesService.deliveredStatusTemplate$ | async) ||\n defaultDeliveredStatus;\n context: getDeliveredStatusContext()\n \"\n ></ng-container>\n </ng-template>\n <ng-template #defaultDeliveredStatus>\n <span\n *ngIf=\"mode === 'main'\"\n class=\"\n str-chat__message-simple-status\n str-chat__message-simple-status-angular\n str-chat__message-status\n \"\n data-testid=\"delivered-indicator\"\n tabindex=\"0\"\n [floatUiLoose]=\"floatingContent\"\n loosePlacement=\"top\"\n [looseTrigger]=\"hasTouchSupport ? 'click' : 'hover'\"\n [disableAnimation]=\"true\"\n [hideOnClickOutside]=\"true\"\n [positionFixed]=\"true\"\n [preventOverflow]=\"true\"\n >\n <float-ui-content #floatingContent>\n <div class=\"str-chat__tooltip str-chat__tooltip-angular\">\n {{ \"streamChat.Delivered\" | translate }}\n </div>\n </float-ui-content>\n <stream-icon-placeholder\n data-testid=\"delivered-icon\"\n icon=\"delivered\"\n ></stream-icon-placeholder>\n </span>\n </ng-template>\n <ng-template #sendingStatus>\n <ng-container\n *ngTemplateOutlet=\"\n (customTemplatesService.sendingStatusTemplate$ | async) ||\n defaultSendingStatus;\n context: getSendingStatusContext()\n \"\n ></ng-container>\n </ng-template>\n <ng-template #defaultSendingStatus>\n <span\n class=\"\n str-chat__message-simple-status\n str-chat__message-simple-status-angular\n str-chat__message-status\n \"\n data-testid=\"sending-indicator\"\n tabindex=\"0\"\n [floatUiLoose]=\"floatingContent\"\n loosePlacement=\"top\"\n [looseTrigger]=\"hasTouchSupport ? 'click' : 'hover'\"\n [disableAnimation]=\"true\"\n [hideOnClickOutside]=\"true\"\n [positionFixed]=\"true\"\n [preventOverflow]=\"true\"\n >\n <float-ui-content #floatingContent>\n <div class=\"str-chat__tooltip str-chat__tooltip-angular\">\n {{ \"streamChat.Sending...\" | translate }}\n </div>\n </float-ui-content>\n <stream-loading-indicator-placeholder\n data-testid=\"loading-indicator\"\n ></stream-loading-indicator-placeholder>\n </span>\n </ng-template>\n <ng-template #readStatus>\n <ng-container\n *ngTemplateOutlet=\"\n (customTemplatesService.readStatusTemplate$ | async) ||\n defaultReadStatus;\n context: getReadStatusContext()\n \"\n ></ng-container>\n </ng-template>\n <ng-template #defaultReadStatus let-readByText=\"readByText\">\n <span\n class=\"\n str-chat__message-simple-status\n str-chat__message-simple-status-angular\n str-chat__message-status\n \"\n data-testid=\"read-indicator\"\n tabindex=\"0\"\n [floatUiLoose]=\"floatingContent\"\n loosePlacement=\"top\"\n [looseTrigger]=\"hasTouchSupport ? 'click' : 'hover'\"\n [disableAnimation]=\"true\"\n [hideOnClickOutside]=\"true\"\n [positionFixed]=\"true\"\n [preventOverflow]=\"true\"\n >\n <float-ui-content #floatingContent>\n <div\n class=\"str-chat__tooltip str-chat__tooltip-angular\"\n data-testid=\"read-by-tooltip\"\n >\n {{ readByText }}\n </div>\n </float-ui-content>\n <stream-icon-placeholder icon=\"read\"></stream-icon-placeholder>\n </span>\n </ng-template>\n </ng-container>\n</ng-template>\n\n<ng-template #replyCountButton>\n <div\n class=\"\n str-chat__message-simple-reply-button\n str-chat__message-replies-count-button-wrapper\n \"\n >\n <button\n *ngIf=\"shouldDisplayThreadLink\"\n class=\"str-chat__message-replies-count-button\"\n data-testid=\"reply-count-button\"\n (click)=\"setAsActiveParentMessage()\"\n >\n {{message?.reply_count === 1 ? ('streamChat.1 reply' | translate) : ('streamChat.{{ replyCount }}\n replies' | translate:replyCountParam)}}\n </button>\n </div>\n</ng-template>\n\n<ng-template #attachmentsTemplate>\n <ng-template\n #defaultAttachments\n let-messageId=\"messageId\"\n let-attachments=\"attachments\"\n let-parentMessageId=\"parentMessageId\"\n let-imageModalStateChangeHandler=\"imageModalStateChangeHandler\"\n >\n <stream-attachment-list\n [messageId]=\"messageId\"\n [attachments]=\"attachments\"\n [parentMessageId]=\"parentMessageId\"\n (imageModalStateChange)=\"imageModalStateChangeHandler($event)\"\n ></stream-attachment-list>\n </ng-template>\n <ng-container\n *ngTemplateOutlet=\"\n (customTemplatesService.attachmentListTemplate$ | async) ||\n defaultAttachments;\n context: getAttachmentListContext()\n \"\n ></ng-container>\n</ng-template>\n", dependencies: [{ kind: "directive", type: i4.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i4.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i4.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: i8.NgxFloatUiContentComponent, selector: "float-ui-content", exportAs: ["ngxFloatUiContent"] }, { kind: "directive", type: i8.NgxFloatUiLooseDirective, selector: "[floatUiLoose]", inputs: ["floatUiLoose", "loosePlacement", "looseTrigger"], exportAs: ["floatUiLoose"] }, { kind: "component", type: AvatarPlaceholderComponent, selector: "stream-avatar-placeholder", inputs: ["name", "imageUrl", "location", "channel", "user", "type", "initialsType", "showOnlineIndicator"] }, { kind: "directive", type: i10.TranslateDirective, selector: "[translate],[ngx-translate]", inputs: ["translate", "translateParams"] }, { kind: "component", type: MessageActionsBoxComponent, selector: "stream-message-actions-box", inputs: ["isMine", "message", "messageTextHtmlElement", "enabledActions"] }, { kind: "component", type: AttachmentListComponent, selector: "stream-attachment-list", inputs: ["messageId", "parentMessageId", "attachments"], outputs: ["imageModalStateChange"] }, { kind: "component", type: MessageReactionsComponent, selector: "stream-message-reactions", inputs: ["messageId", "messageReactionCounts", "latestReactions", "ownReactions"] }, { kind: "component", type: IconPlaceholderComponent, selector: "stream-icon-placeholder", inputs: ["icon"] }, { kind: "component", type: LoadingIndicatorPlaceholderComponent, selector: "stream-loading-indicator-placeholder" }, { kind: "pipe", type: i4.AsyncPipe, name: "async" }, { kind: "pipe", type: i10.TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
5483
+ MessageComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.0.4", type: MessageComponent, selector: "stream-message", inputs: { message: "message", enabledMessageActions: "enabledMessageActions", isLastSentMessage: "isLastSentMessage", mode: "mode", isHighlighted: "isHighlighted", scroll$: "scroll$" }, viewQueries: [{ propertyName: "messageMenuTrigger", first: true, predicate: ["messageMenuTrigger"], descendants: true }, { propertyName: "messageMenuFloat", first: true, predicate: ["messageMenuFloat"], descendants: true }, { propertyName: "messageTextElement", first: true, predicate: ["messageTextElement"], descendants: true }, { propertyName: "messageBubble", first: true, predicate: ["messageBubble"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div\n #container\n data-testid=\"message-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 }} str-chat__message-menu-{{ areMessageOptionsOpen ? 'opened' : 'closed' }}\"\n [class.str-chat__message--me]=\"isSentByCurrentUser\"\n [class.str-chat__message--other]=\"!isSentByCurrentUser\"\n [class.str-chat__message-simple--me]=\"isSentByCurrentUser\"\n [class.str-chat__message--has-attachment]=\"hasAttachment\"\n [class.str-chat__message--with-reactions]=\"hasReactions\"\n [class.str-chat__message--highlighted]=\"isHighlighted\"\n [class.str-chat__message-with-thread-link]=\"shouldDisplayThreadLink\"\n [class.str-chat__message-send-can-be-retried]=\"\n (message?.status === 'failed' && message?.errorStatusCode !== 403) ||\n (message?.type === 'error' && message?.moderation_details)\n \"\n [class.str-chat__message-with-touch-support]=\"hasTouchSupport\"\n [class.str-chat__message-without-touch-support]=\"!hasTouchSupport\"\n>\n <ng-container *ngIf=\"!message?.deleted_at; else deletedMessage\">\n <ng-container *ngIf=\"message?.type !== 'system'; else systemMessage\">\n <stream-avatar-placeholder\n data-testid=\"avatar\"\n class=\"str-chat-angular__avatar-host str-chat__message-sender-avatar\"\n type=\"user\"\n location=\"message-sender\"\n [imageUrl]=\"message?.user?.image\"\n [name]=\"message?.user?.name || message?.user?.id\"\n [user]=\"message?.user || undefined\"\n ></stream-avatar-placeholder>\n <div class=\"str-chat__message-inner\">\n <div\n *ngIf=\"!hasTouchSupport && areOptionsVisible\"\n class=\"str-chat__message-simple__actions str-chat__message-options\"\n data-testid=\"message-options\"\n [class.str-chat__message-actions-open]=\"areMessageOptionsOpen\"\n >\n <div\n #messageActionsToggle\n data-testid=\"message-actions-container\"\n class=\"str-chat__message-actions-container str-chat__message-simple__actions__action str-chat__message-simple__actions__action--options\"\n [floatUiLoose]=\"messageMenuFloat\"\n [looseTrigger]=\"\n messageActionsService.customActionClickHandler ? 'none' : 'click'\n \"\n [hideOnScroll]=\"false\"\n [hideOnClickOutside]=\"true\"\n [hideOnMouseLeave]=\"false\"\n [disableAnimation]=\"false\"\n [preventOverflow]=\"true\"\n [positionFixed]=\"true\"\n (onSHown)=\"areMessageOptionsOpen = true\"\n (onHidden)=\"areMessageOptionsOpen = false\"\n >\n <div\n *ngIf=\"visibleMessageActionsCount > 0\"\n class=\"str-chat__message-actions-box-button\"\n data-testid=\"message-options-button\"\n (click)=\"messageOptionsButtonClicked()\"\n (keyup.enter)=\"messageOptionsButtonClicked()\"\n >\n <stream-icon-placeholder\n icon=\"action\"\n class=\"str-chat__message-action-icon\"\n ></stream-icon-placeholder>\n </div>\n </div>\n </div>\n <div class=\"str-chat__message-reactions-host\">\n <ng-template\n #defaultMessageReactions\n let-messageReactionCounts=\"messageReactionCounts\"\n let-latestReactions=\"latestReactions\"\n let-messageId=\"messageId\"\n let-ownReactions=\"ownReactions\"\n let-messageReactionGroups=\"messageReactionGroups\"\n >\n <stream-message-reactions\n [messageReactionCounts]=\"messageReactionCounts\"\n [latestReactions]=\"latestReactions\"\n [messageId]=\"messageId\"\n [ownReactions]=\"ownReactions\"\n [messageReactionGroups]=\"messageReactionGroups\"\n ></stream-message-reactions>\n </ng-template>\n <ng-container\n *ngTemplateOutlet=\"\n (customTemplatesService.messageReactionsTemplate$ | async) ||\n defaultMessageReactions;\n context: getMessageReactionsContext()\n \"\n ></ng-container>\n </div>\n <float-ui-content #messageMenuFloat>\n <ng-template\n #defaultMessageActionsBox\n let-isMine=\"isMine\"\n let-messageInput=\"message\"\n let-enabledActions=\"enabledActions\"\n let-messageTextHtmlElement=\"messageTextHtmlElement\"\n >\n <stream-message-actions-box\n [isMine]=\"isMine\"\n [message]=\"messageInput\"\n [enabledActions]=\"enabledActions\"\n [messageTextHtmlElement]=\"messageTextHtmlElement\"\n (click)=\"messageActionsBoxClicked(messageMenuFloat)\"\n ></stream-message-actions-box>\n </ng-template>\n <ng-container>\n <ng-container\n *ngTemplateOutlet=\"\n (customTemplatesService.messageActionsBoxTemplate$ | async) ||\n defaultMessageActionsBox;\n context: getMessageActionsBoxContext()\n \"\n >\n </ng-container>\n </ng-container>\n </float-ui-content>\n <div\n class=\"str-chat__message-bubble str-chat-angular__message-bubble\"\n [class.str-chat-angular__message-bubble--attachment-modal-open]=\"\n imageAttachmentModalState === 'opened'\n \"\n data-testid=\"message-bubble\"\n [floatUiLoose]=\"messageMenuFloat\"\n #messageMenuTrigger=\"floatUiLoose\"\n #messageBubble\n looseTrigger=\"none\"\n [hideOnScroll]=\"false\"\n [hideOnClickOutside]=\"true\"\n [hideOnMouseLeave]=\"false\"\n [disableAnimation]=\"true\"\n [preventOverflow]=\"true\"\n (onShown)=\"areMessageOptionsOpen = true\"\n (onHidden)=\"areMessageOptionsOpen = false\"\n [positionFixed]=\"true\"\n >\n <ng-container *ngIf=\"hasAttachment && !message?.quoted_message\">\n <div class=\"str-chat__attachments-container\">\n <ng-container\n *ngTemplateOutlet=\"attachmentsTemplate\"\n ></ng-container>\n </div>\n </ng-container>\n <div\n *ngIf=\"message?.text || (message?.quoted_message && hasAttachment)\"\n class=\"str-chat__message-text\"\n tabindex=\"0\"\n [class.str-chat__message-text--pointer-cursor]=\"\n (message?.status === 'failed' &&\n message?.errorStatusCode !== 403) ||\n (this.message?.type === 'error' &&\n this.message?.moderation_details) ||\n message?.message_text_updated_at\n \"\n (click)=\"messageClicked()\"\n (keyup.enter)=\"messageClicked()\"\n >\n <div\n data-testid=\"inner-message\"\n class=\"str-chat__message-text-inner str-chat__message-simple-text-inner\"\n [class.str-chat__message-light-text-inner--has-attachment]=\"\n hasAttachment\n \"\n >\n <ng-container *ngTemplateOutlet=\"quotedMessage\"></ng-container>\n <ng-container *ngIf=\"hasAttachment && message?.quoted_message\">\n <ng-container\n *ngTemplateOutlet=\"attachmentsTemplate\"\n ></ng-container>\n </ng-container>\n <div\n *ngIf=\"message?.type === 'error'\"\n data-testid=\"client-error-message\"\n class=\"str-chat__simple-message--error-message str-chat__message--error-message\"\n >\n <ng-container *ngIf=\"!message?.moderation_details\">{{\n \"streamChat.Error \u00B7 Unsent\" | translate\n }}</ng-container>\n </div>\n <div\n *ngIf=\"message?.status === 'failed'\"\n data-testid=\"error-message\"\n class=\"str-chat__simple-message--error-message str-chat__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 #messageTextElement data-testid=\"text\">\n <p>\n <ng-container *ngIf=\"messageTextParts; else defaultContent\">\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-template #defaultMention let-content=\"content\">\n <span class=\"str-chat__message-mention\">{{\n content\n }}</span>\n </ng-template>\n <ng-container\n *ngTemplateOutlet=\"\n (customTemplatesService.mentionTemplate$ | async) ||\n defaultMention;\n context: getMentionContext(part)\n \"\n ></ng-container>\n </ng-template>\n </ng-container>\n </ng-container>\n <ng-template #defaultContent>\n <ng-container *ngIf=\"displayAs === 'text'; else asHTML\">\n {{ messageText || \"\" }}\n </ng-container>\n <ng-template #asHTML\n ><span\n data-testid=\"html-content\"\n [innerHTML]=\"messageText\"\n ></span\n ></ng-template>\n </ng-template>\n </p>\n </div>\n </div>\n </div>\n <stream-icon-placeholder\n class=\"str-chat__message-error-icon\"\n icon=\"error\"\n ></stream-icon-placeholder>\n </div>\n </div>\n <ng-container\n *ngTemplateOutlet=\"replyCountButton; context: { message: message }\"\n ></ng-container>\n\n <ng-container *ngTemplateOutlet=\"messageDateAndSender\"></ng-container>\n </ng-container>\n </ng-container>\n</div>\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 <ng-container\n *ngTemplateOutlet=\"\n (customTemplatesService.systemMessageTemplate$ | async) ||\n defaultSystemMessage;\n context: getMessageContext()\n \"\n ></ng-container>\n <ng-template #defaultSystemMessage let-messageInput=\"message\">\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>{{ messageInput?.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</ng-template>\n\n<ng-template #quotedMessage>\n <div\n *ngIf=\"message?.quoted_message\"\n class=\"quoted-message str-chat__quoted-message-preview\"\n data-testid=\"quoted-message-container\"\n [class.mine]=\"isSentByCurrentUser\"\n (click)=\"\n jumpToMessage(\n (message?.quoted_message)!.id,\n message?.quoted_message?.parent_id\n )\n \"\n (keyup.enter)=\"\n jumpToMessage(\n (message?.quoted_message)!.id,\n message?.quoted_message?.parent_id\n )\n \"\n >\n <stream-avatar-placeholder\n data-testid=\"qouted-message-avatar\"\n class=\"str-chat-angular__avatar-host str-chat__message-sender-avatar\"\n type=\"user\"\n location=\"quoted-message-sender\"\n [imageUrl]=\"message?.quoted_message?.user?.image\"\n [name]=\"\n message?.quoted_message?.user?.name || message?.quoted_message?.user?.id\n \"\n [user]=\"message?.quoted_message?.user || undefined\"\n ></stream-avatar-placeholder>\n <div class=\"quoted-message-inner str-chat__quoted-message-bubble\">\n <ng-container\n *ngIf=\"\n message?.quoted_message?.attachments &&\n message?.quoted_message?.attachments?.length\n \"\n >\n <ng-template\n #defaultAttachments\n let-messageId=\"messageId\"\n let-attachments=\"attachments\"\n let-parentMessageId=\"parentMessageId\"\n let-imageModalStateChangeHandler=\"imageModalStateChangeHandler\"\n >\n <stream-attachment-list\n [messageId]=\"messageId\"\n [attachments]=\"attachments\"\n [parentMessageId]=\"parentMessageId\"\n (imageModalStateChange)=\"imageModalStateChangeHandler($event)\"\n ></stream-attachment-list>\n </ng-template>\n <ng-container\n *ngTemplateOutlet=\"\n (customTemplatesService.attachmentListTemplate$ | async) ||\n defaultAttachments;\n context: getQuotedMessageAttachmentListContext()\n \"\n ></ng-container>\n </ng-container>\n <div\n data-testid=\"quoted-message-text\"\n [innerHTML]=\"\n message?.quoted_message?.translation ||\n message?.quoted_message?.html ||\n message?.quoted_message?.text\n \"\n ></div>\n </div>\n </div>\n</ng-template>\n\n<ng-template #messageDateAndSender>\n <ng-container>\n <div\n *ngIf=\"shouldDisplayTranslationNotice\"\n class=\"str-chat__translation-notice\"\n data-testid=\"translation-notice\"\n >\n <button\n *ngIf=\"displayedMessageTextContent === 'translation'\"\n data-testid=\"see-original\"\n translate\n (click)=\"displayOriginalMessage()\"\n (keyup.enter)=\"displayOriginalMessage()\"\n >\n streamChat.See original (automatically translated)\n </button>\n <button\n *ngIf=\"displayedMessageTextContent === 'original'\"\n data-testid=\"see-translation\"\n translate\n (click)=\"displayTranslatedMessage()\"\n (keyup.enter)=\"displayTranslatedMessage()\"\n >\n streamChat.See translation\n </button>\n </div>\n <ng-container\n *ngIf=\"customTemplatesService.customMessageMetadataTemplate$ | async\"\n >\n <div class=\"str-chat__custom-message-metadata\">\n <ng-container\n *ngTemplateOutlet=\"\n (customTemplatesService.customMessageMetadataTemplate$ | async)!;\n context: getMessageMetadataContext()\n \"\n ></ng-container>\n </div>\n </ng-container>\n <div\n class=\"str-chat__message-data str-chat__message-simple-data str-chat__message-metadata\"\n >\n <ng-container *ngTemplateOutlet=\"messageStatus\"></ng-container>\n\n <span\n *ngIf=\"!isSentByCurrentUser\"\n data-testid=\"sender\"\n class=\"str-chat__message-simple-name str-chat__message-sender-name\"\n >\n {{ message?.user?.name ? message?.user?.name : message?.user?.id }}\n </span>\n <span\n data-testid=\"date\"\n class=\"str-chat__message-simple-timestamp str-chat__message-simple-time\"\n >\n {{ parsedDate }}\n </span>\n <ng-container *ngIf=\"message?.message_text_updated_at\">\n <span\n data-testid=\"edited-flag\"\n class=\"str-chat__mesage-simple-edited\"\n translate\n >streamChat.Edited</span\n >\n <div\n data-testid=\"edited-timestamp\"\n class=\"str-chat__message-edited-timestamp\"\n [ngClass]=\"{\n 'str-chat__message-edited-timestamp--open': isEditedFlagOpened,\n 'str-chat__message-edited-timestamp--collapsed': !isEditedFlagOpened\n }\"\n >\n <span translate>streamChat.Edited</span>\n <time\n dateTime=\"{{ message?.message_text_updated_at }}\"\n title=\"{{ message?.message_text_updated_at }}\"\n >\n {{ pasedEditedDate }}\n </time>\n </div>\n </ng-container>\n </div>\n </ng-container>\n</ng-template>\n\n<ng-template #messageStatus>\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' && isMessageDeliveredAndRead && canDisplayReadStatus;\n else deliveredStatus\n \"\n >\n <ng-container *ngTemplateOutlet=\"readStatus\"></ng-container>\n </ng-container>\n </ng-template>\n <ng-template #deliveredStatus>\n <ng-container\n *ngTemplateOutlet=\"\n (customTemplatesService.deliveredStatusTemplate$ | async) ||\n defaultDeliveredStatus;\n context: getDeliveredStatusContext()\n \"\n ></ng-container>\n </ng-template>\n <ng-template #defaultDeliveredStatus>\n <span\n *ngIf=\"mode === 'main'\"\n class=\"str-chat__message-simple-status str-chat__message-simple-status-angular str-chat__message-status\"\n data-testid=\"delivered-indicator\"\n tabindex=\"0\"\n [floatUiLoose]=\"floatingContent\"\n loosePlacement=\"top\"\n [looseTrigger]=\"hasTouchSupport ? 'click' : 'hover'\"\n [disableAnimation]=\"true\"\n [hideOnClickOutside]=\"true\"\n [positionFixed]=\"true\"\n [preventOverflow]=\"true\"\n >\n <float-ui-content #floatingContent>\n <div class=\"str-chat__tooltip str-chat__tooltip-angular\">\n {{ \"streamChat.Delivered\" | translate }}\n </div>\n </float-ui-content>\n <stream-icon-placeholder\n data-testid=\"delivered-icon\"\n icon=\"delivered\"\n ></stream-icon-placeholder>\n </span>\n </ng-template>\n <ng-template #sendingStatus>\n <ng-container\n *ngTemplateOutlet=\"\n (customTemplatesService.sendingStatusTemplate$ | async) ||\n defaultSendingStatus;\n context: getSendingStatusContext()\n \"\n ></ng-container>\n </ng-template>\n <ng-template #defaultSendingStatus>\n <span\n class=\"str-chat__message-simple-status str-chat__message-simple-status-angular str-chat__message-status\"\n data-testid=\"sending-indicator\"\n tabindex=\"0\"\n [floatUiLoose]=\"floatingContent\"\n loosePlacement=\"top\"\n [looseTrigger]=\"hasTouchSupport ? 'click' : 'hover'\"\n [disableAnimation]=\"true\"\n [hideOnClickOutside]=\"true\"\n [positionFixed]=\"true\"\n [preventOverflow]=\"true\"\n >\n <float-ui-content #floatingContent>\n <div class=\"str-chat__tooltip str-chat__tooltip-angular\">\n {{ \"streamChat.Sending...\" | translate }}\n </div>\n </float-ui-content>\n <stream-loading-indicator-placeholder\n data-testid=\"loading-indicator\"\n ></stream-loading-indicator-placeholder>\n </span>\n </ng-template>\n <ng-template #readStatus>\n <ng-container\n *ngTemplateOutlet=\"\n (customTemplatesService.readStatusTemplate$ | async) ||\n defaultReadStatus;\n context: getReadStatusContext()\n \"\n ></ng-container>\n </ng-template>\n <ng-template #defaultReadStatus let-readByText=\"readByText\">\n <span\n class=\"str-chat__message-simple-status str-chat__message-simple-status-angular str-chat__message-status\"\n data-testid=\"read-indicator\"\n tabindex=\"0\"\n [floatUiLoose]=\"floatingContent\"\n loosePlacement=\"top\"\n [looseTrigger]=\"hasTouchSupport ? 'click' : 'hover'\"\n [disableAnimation]=\"true\"\n [hideOnClickOutside]=\"true\"\n [positionFixed]=\"true\"\n [preventOverflow]=\"true\"\n >\n <float-ui-content #floatingContent>\n <div\n class=\"str-chat__tooltip str-chat__tooltip-angular\"\n data-testid=\"read-by-tooltip\"\n >\n {{ readByText }}\n </div>\n </float-ui-content>\n <stream-icon-placeholder icon=\"read\"></stream-icon-placeholder>\n </span>\n </ng-template>\n </ng-container>\n</ng-template>\n\n<ng-template #replyCountButton>\n <div\n class=\"str-chat__message-simple-reply-button str-chat__message-replies-count-button-wrapper\"\n >\n <button\n *ngIf=\"shouldDisplayThreadLink\"\n class=\"str-chat__message-replies-count-button\"\n data-testid=\"reply-count-button\"\n (click)=\"setAsActiveParentMessage()\"\n >\n {{message?.reply_count === 1 ? ('streamChat.1 reply' | translate) : ('streamChat.{{ replyCount }}\n replies' | translate:replyCountParam)}}\n </button>\n </div>\n</ng-template>\n\n<ng-template #attachmentsTemplate>\n <ng-template\n #defaultAttachments\n let-messageId=\"messageId\"\n let-attachments=\"attachments\"\n let-parentMessageId=\"parentMessageId\"\n let-imageModalStateChangeHandler=\"imageModalStateChangeHandler\"\n >\n <stream-attachment-list\n [messageId]=\"messageId\"\n [attachments]=\"attachments\"\n [parentMessageId]=\"parentMessageId\"\n (imageModalStateChange)=\"imageModalStateChangeHandler($event)\"\n ></stream-attachment-list>\n </ng-template>\n <ng-container\n *ngTemplateOutlet=\"\n (customTemplatesService.attachmentListTemplate$ | async) ||\n defaultAttachments;\n context: getAttachmentListContext()\n \"\n ></ng-container>\n</ng-template>\n", dependencies: [{ kind: "directive", type: i4.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i4.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i4.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: i8.NgxFloatUiContentComponent, selector: "float-ui-content", exportAs: ["ngxFloatUiContent"] }, { kind: "directive", type: i8.NgxFloatUiLooseDirective, selector: "[floatUiLoose]", inputs: ["floatUiLoose", "loosePlacement", "looseTrigger"], exportAs: ["floatUiLoose"] }, { kind: "component", type: AvatarPlaceholderComponent, selector: "stream-avatar-placeholder", inputs: ["name", "imageUrl", "location", "channel", "user", "type", "initialsType", "showOnlineIndicator"] }, { kind: "directive", type: i10.TranslateDirective, selector: "[translate],[ngx-translate]", inputs: ["translate", "translateParams"] }, { kind: "component", type: MessageActionsBoxComponent, selector: "stream-message-actions-box", inputs: ["isMine", "message", "messageTextHtmlElement", "enabledActions"] }, { kind: "component", type: AttachmentListComponent, selector: "stream-attachment-list", inputs: ["messageId", "parentMessageId", "attachments"], outputs: ["imageModalStateChange"] }, { kind: "component", type: MessageReactionsComponent, selector: "stream-message-reactions", inputs: ["messageId", "messageReactionGroups", "messageReactionCounts", "latestReactions", "ownReactions"] }, { kind: "component", type: IconPlaceholderComponent, selector: "stream-icon-placeholder", inputs: ["icon"] }, { kind: "component", type: LoadingIndicatorPlaceholderComponent, selector: "stream-loading-indicator-placeholder" }, { kind: "pipe", type: i4.AsyncPipe, name: "async" }, { kind: "pipe", type: i10.TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
5318
5484
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.4", ngImport: i0, type: MessageComponent, decorators: [{
5319
5485
  type: Component,
5320
- args: [{ selector: 'stream-message', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div\n #container\n data-testid=\"message-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 }} str-chat__message-menu-{{ areMessageOptionsOpen ? 'opened' : 'closed' }}\"\n [class.str-chat__message--me]=\"isSentByCurrentUser\"\n [class.str-chat__message--other]=\"!isSentByCurrentUser\"\n [class.str-chat__message-simple--me]=\"isSentByCurrentUser\"\n [class.str-chat__message--has-attachment]=\"hasAttachment\"\n [class.str-chat__message--with-reactions]=\"hasReactions\"\n [class.str-chat__message--highlighted]=\"isHighlighted\"\n [class.str-chat__message-with-thread-link]=\"shouldDisplayThreadLink\"\n [class.str-chat__message-send-can-be-retried]=\"\n (message?.status === 'failed' && message?.errorStatusCode !== 403) ||\n (message?.type === 'error' && message?.moderation_details)\n \"\n [class.str-chat__message-with-touch-support]=\"hasTouchSupport\"\n [class.str-chat__message-without-touch-support]=\"!hasTouchSupport\"\n>\n <ng-container *ngIf=\"!message?.deleted_at; else deletedMessage\">\n <ng-container *ngIf=\"message?.type !== 'system'; else systemMessage\">\n <stream-avatar-placeholder\n data-testid=\"avatar\"\n class=\"str-chat-angular__avatar-host str-chat__message-sender-avatar\"\n type=\"user\"\n location=\"message-sender\"\n [imageUrl]=\"message?.user?.image\"\n [name]=\"message?.user?.name || message?.user?.id\"\n [user]=\"message?.user || undefined\"\n ></stream-avatar-placeholder>\n <div class=\"str-chat__message-inner\">\n <div\n *ngIf=\"!hasTouchSupport && areOptionsVisible\"\n class=\"str-chat__message-simple__actions str-chat__message-options\"\n data-testid=\"message-options\"\n [class.str-chat__message-actions-open]=\"areMessageOptionsOpen\"\n >\n <div\n #messageActionsToggle\n data-testid=\"message-actions-container\"\n class=\"\n str-chat__message-actions-container\n str-chat__message-simple__actions__action\n str-chat__message-simple__actions__action--options\n \"\n [floatUiLoose]=\"messageMenuFloat\"\n [looseTrigger]=\"\n messageActionsService.customActionClickHandler ? 'none' : 'click'\n \"\n [hideOnScroll]=\"false\"\n [hideOnClickOutside]=\"true\"\n [hideOnMouseLeave]=\"false\"\n [disableAnimation]=\"false\"\n [preventOverflow]=\"true\"\n [positionFixed]=\"true\"\n (onSHown)=\"areMessageOptionsOpen = true\"\n (onHidden)=\"areMessageOptionsOpen = false\"\n >\n <div\n *ngIf=\"visibleMessageActionsCount > 0\"\n class=\"str-chat__message-actions-box-button\"\n data-testid=\"message-options-button\"\n (click)=\"messageOptionsButtonClicked()\"\n (keyup.enter)=\"messageOptionsButtonClicked()\"\n >\n <stream-icon-placeholder\n icon=\"action\"\n class=\"str-chat__message-action-icon\"\n ></stream-icon-placeholder>\n </div>\n </div>\n </div>\n <div class=\"str-chat__message-reactions-host\">\n <ng-template\n #defaultMessageReactions\n let-messageReactionCounts=\"messageReactionCounts\"\n let-latestReactions=\"latestReactions\"\n let-messageId=\"messageId\"\n let-ownReactions=\"ownReactions\"\n >\n <stream-message-reactions\n [messageReactionCounts]=\"messageReactionCounts\"\n [latestReactions]=\"latestReactions\"\n [messageId]=\"messageId\"\n [ownReactions]=\"ownReactions\"\n ></stream-message-reactions>\n </ng-template>\n <ng-container\n *ngTemplateOutlet=\"\n (customTemplatesService.messageReactionsTemplate$ | async) ||\n defaultMessageReactions;\n context: getMessageReactionsContext()\n \"\n ></ng-container>\n </div>\n <float-ui-content #messageMenuFloat>\n <ng-template\n #defaultMessageActionsBox\n let-isMine=\"isMine\"\n let-messageInput=\"message\"\n let-enabledActions=\"enabledActions\"\n let-messageTextHtmlElement=\"messageTextHtmlElement\"\n >\n <stream-message-actions-box\n [isMine]=\"isMine\"\n [message]=\"messageInput\"\n [enabledActions]=\"enabledActions\"\n [messageTextHtmlElement]=\"messageTextHtmlElement\"\n (click)=\"messageActionsBoxClicked(messageMenuFloat)\"\n ></stream-message-actions-box>\n </ng-template>\n <ng-container>\n <ng-container\n *ngTemplateOutlet=\"\n (customTemplatesService.messageActionsBoxTemplate$ | async) ||\n defaultMessageActionsBox;\n context: getMessageActionsBoxContext()\n \"\n >\n </ng-container>\n </ng-container>\n </float-ui-content>\n <div\n class=\"str-chat__message-bubble str-chat-angular__message-bubble\"\n [class.str-chat-angular__message-bubble--attachment-modal-open]=\"\n imageAttachmentModalState === 'opened'\n \"\n data-testid=\"message-bubble\"\n [floatUiLoose]=\"messageMenuFloat\"\n #messageMenuTrigger=\"floatUiLoose\"\n #messageBubble\n looseTrigger=\"none\"\n [hideOnScroll]=\"false\"\n [hideOnClickOutside]=\"true\"\n [hideOnMouseLeave]=\"false\"\n [disableAnimation]=\"true\"\n [preventOverflow]=\"true\"\n (onShown)=\"areMessageOptionsOpen = true\"\n (onHidden)=\"areMessageOptionsOpen = false\"\n [positionFixed]=\"true\"\n >\n <ng-container *ngIf=\"hasAttachment && !message?.quoted_message\">\n <div class=\"str-chat__attachments-container\">\n <ng-container\n *ngTemplateOutlet=\"attachmentsTemplate\"\n ></ng-container>\n </div>\n </ng-container>\n <div\n *ngIf=\"message?.text || (message?.quoted_message && hasAttachment)\"\n class=\"str-chat__message-text\"\n tabindex=\"0\"\n [class.str-chat__message-text--pointer-cursor]=\"\n (message?.status === 'failed' &&\n message?.errorStatusCode !== 403) ||\n (this.message?.type === 'error' &&\n this.message?.moderation_details) ||\n message?.message_text_updated_at\n \"\n (click)=\"messageClicked()\"\n (keyup.enter)=\"messageClicked()\"\n >\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 >\n <ng-container *ngTemplateOutlet=\"quotedMessage\"></ng-container>\n <ng-container *ngIf=\"hasAttachment && message?.quoted_message\">\n <ng-container\n *ngTemplateOutlet=\"attachmentsTemplate\"\n ></ng-container>\n </ng-container>\n <div\n *ngIf=\"message?.type === 'error'\"\n data-testid=\"client-error-message\"\n class=\"\n str-chat__simple-message--error-message\n str-chat__message--error-message\n \"\n >\n <ng-container *ngIf=\"!message?.moderation_details\">{{\n \"streamChat.Error \u00B7 Unsent\" | translate\n }}</ng-container>\n </div>\n <div\n *ngIf=\"message?.status === 'failed'\"\n data-testid=\"error-message\"\n class=\"\n str-chat__simple-message--error-message\n str-chat__message--error-message\n \"\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 #messageTextElement data-testid=\"text\">\n <p>\n <ng-container *ngIf=\"messageTextParts; else defaultContent\">\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-template #defaultMention let-content=\"content\">\n <span class=\"str-chat__message-mention\">{{\n content\n }}</span>\n </ng-template>\n <ng-container\n *ngTemplateOutlet=\"\n (customTemplatesService.mentionTemplate$ | async) ||\n defaultMention;\n context: getMentionContext(part)\n \"\n ></ng-container>\n </ng-template>\n </ng-container>\n </ng-container>\n <ng-template #defaultContent>\n <ng-container *ngIf=\"displayAs === 'text'; else asHTML\">\n {{ messageText || \"\" }}\n </ng-container>\n <ng-template #asHTML\n ><span\n data-testid=\"html-content\"\n [innerHTML]=\"messageText\"\n ></span\n ></ng-template>\n </ng-template>\n </p>\n </div>\n </div>\n </div>\n <stream-icon-placeholder\n class=\"str-chat__message-error-icon\"\n icon=\"error\"\n ></stream-icon-placeholder>\n </div>\n </div>\n <ng-container\n *ngTemplateOutlet=\"replyCountButton; context: { message: message }\"\n ></ng-container>\n\n <ng-container *ngTemplateOutlet=\"messageDateAndSender\"></ng-container>\n </ng-container>\n </ng-container>\n</div>\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 <ng-container\n *ngTemplateOutlet=\"\n (customTemplatesService.systemMessageTemplate$ | async) ||\n defaultSystemMessage;\n context: getMessageContext()\n \"\n ></ng-container>\n <ng-template #defaultSystemMessage let-messageInput=\"message\">\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>{{ messageInput?.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</ng-template>\n\n<ng-template #quotedMessage>\n <div\n *ngIf=\"message?.quoted_message\"\n class=\"quoted-message str-chat__quoted-message-preview\"\n data-testid=\"quoted-message-container\"\n [class.mine]=\"isSentByCurrentUser\"\n (click)=\"\n jumpToMessage(\n (message?.quoted_message)!.id,\n message?.quoted_message?.parent_id\n )\n \"\n (keyup.enter)=\"\n jumpToMessage(\n (message?.quoted_message)!.id,\n message?.quoted_message?.parent_id\n )\n \"\n >\n <stream-avatar-placeholder\n data-testid=\"qouted-message-avatar\"\n class=\"str-chat-angular__avatar-host str-chat__message-sender-avatar\"\n type=\"user\"\n location=\"quoted-message-sender\"\n [imageUrl]=\"message?.quoted_message?.user?.image\"\n [name]=\"\n message?.quoted_message?.user?.name || message?.quoted_message?.user?.id\n \"\n [user]=\"message?.quoted_message?.user || undefined\"\n ></stream-avatar-placeholder>\n <div class=\"quoted-message-inner str-chat__quoted-message-bubble\">\n <ng-container\n *ngIf=\"\n message?.quoted_message?.attachments &&\n message?.quoted_message?.attachments?.length\n \"\n >\n <ng-template\n #defaultAttachments\n let-messageId=\"messageId\"\n let-attachments=\"attachments\"\n let-parentMessageId=\"parentMessageId\"\n let-imageModalStateChangeHandler=\"imageModalStateChangeHandler\"\n >\n <stream-attachment-list\n [messageId]=\"messageId\"\n [attachments]=\"attachments\"\n [parentMessageId]=\"parentMessageId\"\n (imageModalStateChange)=\"imageModalStateChangeHandler($event)\"\n ></stream-attachment-list>\n </ng-template>\n <ng-container\n *ngTemplateOutlet=\"\n (customTemplatesService.attachmentListTemplate$ | async) ||\n defaultAttachments;\n context: getQuotedMessageAttachmentListContext()\n \"\n ></ng-container>\n </ng-container>\n <div\n data-testid=\"quoted-message-text\"\n [innerHTML]=\"\n message?.quoted_message?.translation ||\n message?.quoted_message?.html ||\n message?.quoted_message?.text\n \"\n ></div>\n </div>\n </div>\n</ng-template>\n\n<ng-template #messageDateAndSender>\n <ng-container>\n <div\n *ngIf=\"shouldDisplayTranslationNotice\"\n class=\"str-chat__translation-notice\"\n data-testid=\"translation-notice\"\n >\n <button\n *ngIf=\"displayedMessageTextContent === 'translation'\"\n data-testid=\"see-original\"\n translate\n (click)=\"displayOriginalMessage()\"\n (keyup.enter)=\"displayOriginalMessage()\"\n >\n streamChat.See original (automatically translated)\n </button>\n <button\n *ngIf=\"displayedMessageTextContent === 'original'\"\n data-testid=\"see-translation\"\n translate\n (click)=\"displayTranslatedMessage()\"\n (keyup.enter)=\"displayTranslatedMessage()\"\n >\n streamChat.See translation\n </button>\n </div>\n <ng-container\n *ngIf=\"customTemplatesService.customMessageMetadataTemplate$ | async\"\n >\n <div class=\"str-chat__custom-message-metadata\">\n <ng-container\n *ngTemplateOutlet=\"\n (customTemplatesService.customMessageMetadataTemplate$ | async)!;\n context: getMessageMetadataContext()\n \"\n ></ng-container>\n </div>\n </ng-container>\n <div\n class=\"\n str-chat__message-data\n str-chat__message-simple-data\n str-chat__message-metadata\n \"\n >\n <ng-container *ngTemplateOutlet=\"messageStatus\"></ng-container>\n\n <span\n *ngIf=\"!isSentByCurrentUser\"\n data-testid=\"sender\"\n class=\"str-chat__message-simple-name str-chat__message-sender-name\"\n >\n {{ message?.user?.name ? message?.user?.name : message?.user?.id }}\n </span>\n <span\n data-testid=\"date\"\n class=\"str-chat__message-simple-timestamp str-chat__message-simple-time\"\n >\n {{ parsedDate }}\n </span>\n <ng-container *ngIf=\"message?.message_text_updated_at\">\n <span\n data-testid=\"edited-flag\"\n class=\"str-chat__mesage-simple-edited\"\n translate\n >streamChat.Edited</span\n >\n <div\n data-testid=\"edited-timestamp\"\n class=\"str-chat__message-edited-timestamp\"\n [ngClass]=\"{\n 'str-chat__message-edited-timestamp--open': isEditedFlagOpened,\n 'str-chat__message-edited-timestamp--collapsed': !isEditedFlagOpened\n }\"\n >\n <span translate>streamChat.Edited</span>\n <time\n dateTime=\"{{ message?.message_text_updated_at }}\"\n title=\"{{ message?.message_text_updated_at }}\"\n >\n {{ pasedEditedDate }}\n </time>\n </div>\n </ng-container>\n </div>\n </ng-container>\n</ng-template>\n\n<ng-template #messageStatus>\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' && isMessageDeliveredAndRead && canDisplayReadStatus;\n else deliveredStatus\n \"\n >\n <ng-container *ngTemplateOutlet=\"readStatus\"></ng-container>\n </ng-container>\n </ng-template>\n <ng-template #deliveredStatus>\n <ng-container\n *ngTemplateOutlet=\"\n (customTemplatesService.deliveredStatusTemplate$ | async) ||\n defaultDeliveredStatus;\n context: getDeliveredStatusContext()\n \"\n ></ng-container>\n </ng-template>\n <ng-template #defaultDeliveredStatus>\n <span\n *ngIf=\"mode === 'main'\"\n class=\"\n str-chat__message-simple-status\n str-chat__message-simple-status-angular\n str-chat__message-status\n \"\n data-testid=\"delivered-indicator\"\n tabindex=\"0\"\n [floatUiLoose]=\"floatingContent\"\n loosePlacement=\"top\"\n [looseTrigger]=\"hasTouchSupport ? 'click' : 'hover'\"\n [disableAnimation]=\"true\"\n [hideOnClickOutside]=\"true\"\n [positionFixed]=\"true\"\n [preventOverflow]=\"true\"\n >\n <float-ui-content #floatingContent>\n <div class=\"str-chat__tooltip str-chat__tooltip-angular\">\n {{ \"streamChat.Delivered\" | translate }}\n </div>\n </float-ui-content>\n <stream-icon-placeholder\n data-testid=\"delivered-icon\"\n icon=\"delivered\"\n ></stream-icon-placeholder>\n </span>\n </ng-template>\n <ng-template #sendingStatus>\n <ng-container\n *ngTemplateOutlet=\"\n (customTemplatesService.sendingStatusTemplate$ | async) ||\n defaultSendingStatus;\n context: getSendingStatusContext()\n \"\n ></ng-container>\n </ng-template>\n <ng-template #defaultSendingStatus>\n <span\n class=\"\n str-chat__message-simple-status\n str-chat__message-simple-status-angular\n str-chat__message-status\n \"\n data-testid=\"sending-indicator\"\n tabindex=\"0\"\n [floatUiLoose]=\"floatingContent\"\n loosePlacement=\"top\"\n [looseTrigger]=\"hasTouchSupport ? 'click' : 'hover'\"\n [disableAnimation]=\"true\"\n [hideOnClickOutside]=\"true\"\n [positionFixed]=\"true\"\n [preventOverflow]=\"true\"\n >\n <float-ui-content #floatingContent>\n <div class=\"str-chat__tooltip str-chat__tooltip-angular\">\n {{ \"streamChat.Sending...\" | translate }}\n </div>\n </float-ui-content>\n <stream-loading-indicator-placeholder\n data-testid=\"loading-indicator\"\n ></stream-loading-indicator-placeholder>\n </span>\n </ng-template>\n <ng-template #readStatus>\n <ng-container\n *ngTemplateOutlet=\"\n (customTemplatesService.readStatusTemplate$ | async) ||\n defaultReadStatus;\n context: getReadStatusContext()\n \"\n ></ng-container>\n </ng-template>\n <ng-template #defaultReadStatus let-readByText=\"readByText\">\n <span\n class=\"\n str-chat__message-simple-status\n str-chat__message-simple-status-angular\n str-chat__message-status\n \"\n data-testid=\"read-indicator\"\n tabindex=\"0\"\n [floatUiLoose]=\"floatingContent\"\n loosePlacement=\"top\"\n [looseTrigger]=\"hasTouchSupport ? 'click' : 'hover'\"\n [disableAnimation]=\"true\"\n [hideOnClickOutside]=\"true\"\n [positionFixed]=\"true\"\n [preventOverflow]=\"true\"\n >\n <float-ui-content #floatingContent>\n <div\n class=\"str-chat__tooltip str-chat__tooltip-angular\"\n data-testid=\"read-by-tooltip\"\n >\n {{ readByText }}\n </div>\n </float-ui-content>\n <stream-icon-placeholder icon=\"read\"></stream-icon-placeholder>\n </span>\n </ng-template>\n </ng-container>\n</ng-template>\n\n<ng-template #replyCountButton>\n <div\n class=\"\n str-chat__message-simple-reply-button\n str-chat__message-replies-count-button-wrapper\n \"\n >\n <button\n *ngIf=\"shouldDisplayThreadLink\"\n class=\"str-chat__message-replies-count-button\"\n data-testid=\"reply-count-button\"\n (click)=\"setAsActiveParentMessage()\"\n >\n {{message?.reply_count === 1 ? ('streamChat.1 reply' | translate) : ('streamChat.{{ replyCount }}\n replies' | translate:replyCountParam)}}\n </button>\n </div>\n</ng-template>\n\n<ng-template #attachmentsTemplate>\n <ng-template\n #defaultAttachments\n let-messageId=\"messageId\"\n let-attachments=\"attachments\"\n let-parentMessageId=\"parentMessageId\"\n let-imageModalStateChangeHandler=\"imageModalStateChangeHandler\"\n >\n <stream-attachment-list\n [messageId]=\"messageId\"\n [attachments]=\"attachments\"\n [parentMessageId]=\"parentMessageId\"\n (imageModalStateChange)=\"imageModalStateChangeHandler($event)\"\n ></stream-attachment-list>\n </ng-template>\n <ng-container\n *ngTemplateOutlet=\"\n (customTemplatesService.attachmentListTemplate$ | async) ||\n defaultAttachments;\n context: getAttachmentListContext()\n \"\n ></ng-container>\n</ng-template>\n" }]
5486
+ args: [{ selector: 'stream-message', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div\n #container\n data-testid=\"message-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 }} str-chat__message-menu-{{ areMessageOptionsOpen ? 'opened' : 'closed' }}\"\n [class.str-chat__message--me]=\"isSentByCurrentUser\"\n [class.str-chat__message--other]=\"!isSentByCurrentUser\"\n [class.str-chat__message-simple--me]=\"isSentByCurrentUser\"\n [class.str-chat__message--has-attachment]=\"hasAttachment\"\n [class.str-chat__message--with-reactions]=\"hasReactions\"\n [class.str-chat__message--highlighted]=\"isHighlighted\"\n [class.str-chat__message-with-thread-link]=\"shouldDisplayThreadLink\"\n [class.str-chat__message-send-can-be-retried]=\"\n (message?.status === 'failed' && message?.errorStatusCode !== 403) ||\n (message?.type === 'error' && message?.moderation_details)\n \"\n [class.str-chat__message-with-touch-support]=\"hasTouchSupport\"\n [class.str-chat__message-without-touch-support]=\"!hasTouchSupport\"\n>\n <ng-container *ngIf=\"!message?.deleted_at; else deletedMessage\">\n <ng-container *ngIf=\"message?.type !== 'system'; else systemMessage\">\n <stream-avatar-placeholder\n data-testid=\"avatar\"\n class=\"str-chat-angular__avatar-host str-chat__message-sender-avatar\"\n type=\"user\"\n location=\"message-sender\"\n [imageUrl]=\"message?.user?.image\"\n [name]=\"message?.user?.name || message?.user?.id\"\n [user]=\"message?.user || undefined\"\n ></stream-avatar-placeholder>\n <div class=\"str-chat__message-inner\">\n <div\n *ngIf=\"!hasTouchSupport && areOptionsVisible\"\n class=\"str-chat__message-simple__actions str-chat__message-options\"\n data-testid=\"message-options\"\n [class.str-chat__message-actions-open]=\"areMessageOptionsOpen\"\n >\n <div\n #messageActionsToggle\n data-testid=\"message-actions-container\"\n class=\"str-chat__message-actions-container str-chat__message-simple__actions__action str-chat__message-simple__actions__action--options\"\n [floatUiLoose]=\"messageMenuFloat\"\n [looseTrigger]=\"\n messageActionsService.customActionClickHandler ? 'none' : 'click'\n \"\n [hideOnScroll]=\"false\"\n [hideOnClickOutside]=\"true\"\n [hideOnMouseLeave]=\"false\"\n [disableAnimation]=\"false\"\n [preventOverflow]=\"true\"\n [positionFixed]=\"true\"\n (onSHown)=\"areMessageOptionsOpen = true\"\n (onHidden)=\"areMessageOptionsOpen = false\"\n >\n <div\n *ngIf=\"visibleMessageActionsCount > 0\"\n class=\"str-chat__message-actions-box-button\"\n data-testid=\"message-options-button\"\n (click)=\"messageOptionsButtonClicked()\"\n (keyup.enter)=\"messageOptionsButtonClicked()\"\n >\n <stream-icon-placeholder\n icon=\"action\"\n class=\"str-chat__message-action-icon\"\n ></stream-icon-placeholder>\n </div>\n </div>\n </div>\n <div class=\"str-chat__message-reactions-host\">\n <ng-template\n #defaultMessageReactions\n let-messageReactionCounts=\"messageReactionCounts\"\n let-latestReactions=\"latestReactions\"\n let-messageId=\"messageId\"\n let-ownReactions=\"ownReactions\"\n let-messageReactionGroups=\"messageReactionGroups\"\n >\n <stream-message-reactions\n [messageReactionCounts]=\"messageReactionCounts\"\n [latestReactions]=\"latestReactions\"\n [messageId]=\"messageId\"\n [ownReactions]=\"ownReactions\"\n [messageReactionGroups]=\"messageReactionGroups\"\n ></stream-message-reactions>\n </ng-template>\n <ng-container\n *ngTemplateOutlet=\"\n (customTemplatesService.messageReactionsTemplate$ | async) ||\n defaultMessageReactions;\n context: getMessageReactionsContext()\n \"\n ></ng-container>\n </div>\n <float-ui-content #messageMenuFloat>\n <ng-template\n #defaultMessageActionsBox\n let-isMine=\"isMine\"\n let-messageInput=\"message\"\n let-enabledActions=\"enabledActions\"\n let-messageTextHtmlElement=\"messageTextHtmlElement\"\n >\n <stream-message-actions-box\n [isMine]=\"isMine\"\n [message]=\"messageInput\"\n [enabledActions]=\"enabledActions\"\n [messageTextHtmlElement]=\"messageTextHtmlElement\"\n (click)=\"messageActionsBoxClicked(messageMenuFloat)\"\n ></stream-message-actions-box>\n </ng-template>\n <ng-container>\n <ng-container\n *ngTemplateOutlet=\"\n (customTemplatesService.messageActionsBoxTemplate$ | async) ||\n defaultMessageActionsBox;\n context: getMessageActionsBoxContext()\n \"\n >\n </ng-container>\n </ng-container>\n </float-ui-content>\n <div\n class=\"str-chat__message-bubble str-chat-angular__message-bubble\"\n [class.str-chat-angular__message-bubble--attachment-modal-open]=\"\n imageAttachmentModalState === 'opened'\n \"\n data-testid=\"message-bubble\"\n [floatUiLoose]=\"messageMenuFloat\"\n #messageMenuTrigger=\"floatUiLoose\"\n #messageBubble\n looseTrigger=\"none\"\n [hideOnScroll]=\"false\"\n [hideOnClickOutside]=\"true\"\n [hideOnMouseLeave]=\"false\"\n [disableAnimation]=\"true\"\n [preventOverflow]=\"true\"\n (onShown)=\"areMessageOptionsOpen = true\"\n (onHidden)=\"areMessageOptionsOpen = false\"\n [positionFixed]=\"true\"\n >\n <ng-container *ngIf=\"hasAttachment && !message?.quoted_message\">\n <div class=\"str-chat__attachments-container\">\n <ng-container\n *ngTemplateOutlet=\"attachmentsTemplate\"\n ></ng-container>\n </div>\n </ng-container>\n <div\n *ngIf=\"message?.text || (message?.quoted_message && hasAttachment)\"\n class=\"str-chat__message-text\"\n tabindex=\"0\"\n [class.str-chat__message-text--pointer-cursor]=\"\n (message?.status === 'failed' &&\n message?.errorStatusCode !== 403) ||\n (this.message?.type === 'error' &&\n this.message?.moderation_details) ||\n message?.message_text_updated_at\n \"\n (click)=\"messageClicked()\"\n (keyup.enter)=\"messageClicked()\"\n >\n <div\n data-testid=\"inner-message\"\n class=\"str-chat__message-text-inner str-chat__message-simple-text-inner\"\n [class.str-chat__message-light-text-inner--has-attachment]=\"\n hasAttachment\n \"\n >\n <ng-container *ngTemplateOutlet=\"quotedMessage\"></ng-container>\n <ng-container *ngIf=\"hasAttachment && message?.quoted_message\">\n <ng-container\n *ngTemplateOutlet=\"attachmentsTemplate\"\n ></ng-container>\n </ng-container>\n <div\n *ngIf=\"message?.type === 'error'\"\n data-testid=\"client-error-message\"\n class=\"str-chat__simple-message--error-message str-chat__message--error-message\"\n >\n <ng-container *ngIf=\"!message?.moderation_details\">{{\n \"streamChat.Error \u00B7 Unsent\" | translate\n }}</ng-container>\n </div>\n <div\n *ngIf=\"message?.status === 'failed'\"\n data-testid=\"error-message\"\n class=\"str-chat__simple-message--error-message str-chat__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 #messageTextElement data-testid=\"text\">\n <p>\n <ng-container *ngIf=\"messageTextParts; else defaultContent\">\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-template #defaultMention let-content=\"content\">\n <span class=\"str-chat__message-mention\">{{\n content\n }}</span>\n </ng-template>\n <ng-container\n *ngTemplateOutlet=\"\n (customTemplatesService.mentionTemplate$ | async) ||\n defaultMention;\n context: getMentionContext(part)\n \"\n ></ng-container>\n </ng-template>\n </ng-container>\n </ng-container>\n <ng-template #defaultContent>\n <ng-container *ngIf=\"displayAs === 'text'; else asHTML\">\n {{ messageText || \"\" }}\n </ng-container>\n <ng-template #asHTML\n ><span\n data-testid=\"html-content\"\n [innerHTML]=\"messageText\"\n ></span\n ></ng-template>\n </ng-template>\n </p>\n </div>\n </div>\n </div>\n <stream-icon-placeholder\n class=\"str-chat__message-error-icon\"\n icon=\"error\"\n ></stream-icon-placeholder>\n </div>\n </div>\n <ng-container\n *ngTemplateOutlet=\"replyCountButton; context: { message: message }\"\n ></ng-container>\n\n <ng-container *ngTemplateOutlet=\"messageDateAndSender\"></ng-container>\n </ng-container>\n </ng-container>\n</div>\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 <ng-container\n *ngTemplateOutlet=\"\n (customTemplatesService.systemMessageTemplate$ | async) ||\n defaultSystemMessage;\n context: getMessageContext()\n \"\n ></ng-container>\n <ng-template #defaultSystemMessage let-messageInput=\"message\">\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>{{ messageInput?.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</ng-template>\n\n<ng-template #quotedMessage>\n <div\n *ngIf=\"message?.quoted_message\"\n class=\"quoted-message str-chat__quoted-message-preview\"\n data-testid=\"quoted-message-container\"\n [class.mine]=\"isSentByCurrentUser\"\n (click)=\"\n jumpToMessage(\n (message?.quoted_message)!.id,\n message?.quoted_message?.parent_id\n )\n \"\n (keyup.enter)=\"\n jumpToMessage(\n (message?.quoted_message)!.id,\n message?.quoted_message?.parent_id\n )\n \"\n >\n <stream-avatar-placeholder\n data-testid=\"qouted-message-avatar\"\n class=\"str-chat-angular__avatar-host str-chat__message-sender-avatar\"\n type=\"user\"\n location=\"quoted-message-sender\"\n [imageUrl]=\"message?.quoted_message?.user?.image\"\n [name]=\"\n message?.quoted_message?.user?.name || message?.quoted_message?.user?.id\n \"\n [user]=\"message?.quoted_message?.user || undefined\"\n ></stream-avatar-placeholder>\n <div class=\"quoted-message-inner str-chat__quoted-message-bubble\">\n <ng-container\n *ngIf=\"\n message?.quoted_message?.attachments &&\n message?.quoted_message?.attachments?.length\n \"\n >\n <ng-template\n #defaultAttachments\n let-messageId=\"messageId\"\n let-attachments=\"attachments\"\n let-parentMessageId=\"parentMessageId\"\n let-imageModalStateChangeHandler=\"imageModalStateChangeHandler\"\n >\n <stream-attachment-list\n [messageId]=\"messageId\"\n [attachments]=\"attachments\"\n [parentMessageId]=\"parentMessageId\"\n (imageModalStateChange)=\"imageModalStateChangeHandler($event)\"\n ></stream-attachment-list>\n </ng-template>\n <ng-container\n *ngTemplateOutlet=\"\n (customTemplatesService.attachmentListTemplate$ | async) ||\n defaultAttachments;\n context: getQuotedMessageAttachmentListContext()\n \"\n ></ng-container>\n </ng-container>\n <div\n data-testid=\"quoted-message-text\"\n [innerHTML]=\"\n message?.quoted_message?.translation ||\n message?.quoted_message?.html ||\n message?.quoted_message?.text\n \"\n ></div>\n </div>\n </div>\n</ng-template>\n\n<ng-template #messageDateAndSender>\n <ng-container>\n <div\n *ngIf=\"shouldDisplayTranslationNotice\"\n class=\"str-chat__translation-notice\"\n data-testid=\"translation-notice\"\n >\n <button\n *ngIf=\"displayedMessageTextContent === 'translation'\"\n data-testid=\"see-original\"\n translate\n (click)=\"displayOriginalMessage()\"\n (keyup.enter)=\"displayOriginalMessage()\"\n >\n streamChat.See original (automatically translated)\n </button>\n <button\n *ngIf=\"displayedMessageTextContent === 'original'\"\n data-testid=\"see-translation\"\n translate\n (click)=\"displayTranslatedMessage()\"\n (keyup.enter)=\"displayTranslatedMessage()\"\n >\n streamChat.See translation\n </button>\n </div>\n <ng-container\n *ngIf=\"customTemplatesService.customMessageMetadataTemplate$ | async\"\n >\n <div class=\"str-chat__custom-message-metadata\">\n <ng-container\n *ngTemplateOutlet=\"\n (customTemplatesService.customMessageMetadataTemplate$ | async)!;\n context: getMessageMetadataContext()\n \"\n ></ng-container>\n </div>\n </ng-container>\n <div\n class=\"str-chat__message-data str-chat__message-simple-data str-chat__message-metadata\"\n >\n <ng-container *ngTemplateOutlet=\"messageStatus\"></ng-container>\n\n <span\n *ngIf=\"!isSentByCurrentUser\"\n data-testid=\"sender\"\n class=\"str-chat__message-simple-name str-chat__message-sender-name\"\n >\n {{ message?.user?.name ? message?.user?.name : message?.user?.id }}\n </span>\n <span\n data-testid=\"date\"\n class=\"str-chat__message-simple-timestamp str-chat__message-simple-time\"\n >\n {{ parsedDate }}\n </span>\n <ng-container *ngIf=\"message?.message_text_updated_at\">\n <span\n data-testid=\"edited-flag\"\n class=\"str-chat__mesage-simple-edited\"\n translate\n >streamChat.Edited</span\n >\n <div\n data-testid=\"edited-timestamp\"\n class=\"str-chat__message-edited-timestamp\"\n [ngClass]=\"{\n 'str-chat__message-edited-timestamp--open': isEditedFlagOpened,\n 'str-chat__message-edited-timestamp--collapsed': !isEditedFlagOpened\n }\"\n >\n <span translate>streamChat.Edited</span>\n <time\n dateTime=\"{{ message?.message_text_updated_at }}\"\n title=\"{{ message?.message_text_updated_at }}\"\n >\n {{ pasedEditedDate }}\n </time>\n </div>\n </ng-container>\n </div>\n </ng-container>\n</ng-template>\n\n<ng-template #messageStatus>\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' && isMessageDeliveredAndRead && canDisplayReadStatus;\n else deliveredStatus\n \"\n >\n <ng-container *ngTemplateOutlet=\"readStatus\"></ng-container>\n </ng-container>\n </ng-template>\n <ng-template #deliveredStatus>\n <ng-container\n *ngTemplateOutlet=\"\n (customTemplatesService.deliveredStatusTemplate$ | async) ||\n defaultDeliveredStatus;\n context: getDeliveredStatusContext()\n \"\n ></ng-container>\n </ng-template>\n <ng-template #defaultDeliveredStatus>\n <span\n *ngIf=\"mode === 'main'\"\n class=\"str-chat__message-simple-status str-chat__message-simple-status-angular str-chat__message-status\"\n data-testid=\"delivered-indicator\"\n tabindex=\"0\"\n [floatUiLoose]=\"floatingContent\"\n loosePlacement=\"top\"\n [looseTrigger]=\"hasTouchSupport ? 'click' : 'hover'\"\n [disableAnimation]=\"true\"\n [hideOnClickOutside]=\"true\"\n [positionFixed]=\"true\"\n [preventOverflow]=\"true\"\n >\n <float-ui-content #floatingContent>\n <div class=\"str-chat__tooltip str-chat__tooltip-angular\">\n {{ \"streamChat.Delivered\" | translate }}\n </div>\n </float-ui-content>\n <stream-icon-placeholder\n data-testid=\"delivered-icon\"\n icon=\"delivered\"\n ></stream-icon-placeholder>\n </span>\n </ng-template>\n <ng-template #sendingStatus>\n <ng-container\n *ngTemplateOutlet=\"\n (customTemplatesService.sendingStatusTemplate$ | async) ||\n defaultSendingStatus;\n context: getSendingStatusContext()\n \"\n ></ng-container>\n </ng-template>\n <ng-template #defaultSendingStatus>\n <span\n class=\"str-chat__message-simple-status str-chat__message-simple-status-angular str-chat__message-status\"\n data-testid=\"sending-indicator\"\n tabindex=\"0\"\n [floatUiLoose]=\"floatingContent\"\n loosePlacement=\"top\"\n [looseTrigger]=\"hasTouchSupport ? 'click' : 'hover'\"\n [disableAnimation]=\"true\"\n [hideOnClickOutside]=\"true\"\n [positionFixed]=\"true\"\n [preventOverflow]=\"true\"\n >\n <float-ui-content #floatingContent>\n <div class=\"str-chat__tooltip str-chat__tooltip-angular\">\n {{ \"streamChat.Sending...\" | translate }}\n </div>\n </float-ui-content>\n <stream-loading-indicator-placeholder\n data-testid=\"loading-indicator\"\n ></stream-loading-indicator-placeholder>\n </span>\n </ng-template>\n <ng-template #readStatus>\n <ng-container\n *ngTemplateOutlet=\"\n (customTemplatesService.readStatusTemplate$ | async) ||\n defaultReadStatus;\n context: getReadStatusContext()\n \"\n ></ng-container>\n </ng-template>\n <ng-template #defaultReadStatus let-readByText=\"readByText\">\n <span\n class=\"str-chat__message-simple-status str-chat__message-simple-status-angular str-chat__message-status\"\n data-testid=\"read-indicator\"\n tabindex=\"0\"\n [floatUiLoose]=\"floatingContent\"\n loosePlacement=\"top\"\n [looseTrigger]=\"hasTouchSupport ? 'click' : 'hover'\"\n [disableAnimation]=\"true\"\n [hideOnClickOutside]=\"true\"\n [positionFixed]=\"true\"\n [preventOverflow]=\"true\"\n >\n <float-ui-content #floatingContent>\n <div\n class=\"str-chat__tooltip str-chat__tooltip-angular\"\n data-testid=\"read-by-tooltip\"\n >\n {{ readByText }}\n </div>\n </float-ui-content>\n <stream-icon-placeholder icon=\"read\"></stream-icon-placeholder>\n </span>\n </ng-template>\n </ng-container>\n</ng-template>\n\n<ng-template #replyCountButton>\n <div\n class=\"str-chat__message-simple-reply-button str-chat__message-replies-count-button-wrapper\"\n >\n <button\n *ngIf=\"shouldDisplayThreadLink\"\n class=\"str-chat__message-replies-count-button\"\n data-testid=\"reply-count-button\"\n (click)=\"setAsActiveParentMessage()\"\n >\n {{message?.reply_count === 1 ? ('streamChat.1 reply' | translate) : ('streamChat.{{ replyCount }}\n replies' | translate:replyCountParam)}}\n </button>\n </div>\n</ng-template>\n\n<ng-template #attachmentsTemplate>\n <ng-template\n #defaultAttachments\n let-messageId=\"messageId\"\n let-attachments=\"attachments\"\n let-parentMessageId=\"parentMessageId\"\n let-imageModalStateChangeHandler=\"imageModalStateChangeHandler\"\n >\n <stream-attachment-list\n [messageId]=\"messageId\"\n [attachments]=\"attachments\"\n [parentMessageId]=\"parentMessageId\"\n (imageModalStateChange)=\"imageModalStateChangeHandler($event)\"\n ></stream-attachment-list>\n </ng-template>\n <ng-container\n *ngTemplateOutlet=\"\n (customTemplatesService.attachmentListTemplate$ | async) ||\n defaultAttachments;\n context: getAttachmentListContext()\n \"\n ></ng-container>\n</ng-template>\n" }]
5321
5487
  }], ctorParameters: function () { return [{ type: ChatClientService }, { type: ChannelService }, { type: CustomTemplatesService }, { type: i0.ChangeDetectorRef }, { type: DateParserService }, { type: MessageService }, { type: MessageActionsService }, { type: i0.NgZone }]; }, propDecorators: { message: [{
5322
5488
  type: Input
5323
5489
  }], enabledMessageActions: [{
@@ -5910,10 +6076,10 @@ class MessageInputComponent {
5910
6076
  }
5911
6077
  }
5912
6078
  MessageInputComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.4", ngImport: i0, type: MessageInputComponent, deps: [{ token: ChannelService }, { token: NotificationService }, { token: AttachmentService }, { token: MessageInputConfigService }, { token: textareaInjectionToken }, { token: i0.ComponentFactoryResolver }, { token: i0.ChangeDetectorRef }, { token: EmojiInputService }, { token: CustomTemplatesService }, { token: MessageActionsService }], target: i0.ɵɵFactoryTarget.Component });
5913
- MessageInputComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.0.4", type: MessageInputComponent, selector: "stream-message-input", inputs: { isFileUploadEnabled: "isFileUploadEnabled", areMentionsEnabled: "areMentionsEnabled", mentionScope: "mentionScope", mode: "mode", isMultipleFileUploadEnabled: "isMultipleFileUploadEnabled", message: "message", sendMessage$: "sendMessage$", inputMode: "inputMode", autoFocus: "autoFocus", watchForMessageToEdit: "watchForMessageToEdit", displaySendButton: "displaySendButton" }, outputs: { messageUpdate: "messageUpdate" }, host: { properties: { "class": "this.class" } }, providers: [AttachmentService, EmojiInputService], viewQueries: [{ propertyName: "fileInput", first: true, predicate: ["fileInput"], descendants: true }, { propertyName: "textareaAnchor", first: true, predicate: TextareaDirective, descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div class=\"str-chat__message-input str-chat-angular__message-input\">\n <div *ngIf=\"quotedMessage\" class=\"str-chat__quoted-message-preview-header\">\n <div class=\"str-chat__quoted-message-reply-to-message\">\n {{ \"streamChat.Reply to Message\" | translate }}\n </div>\n <button\n class=\"str-chat__quoted-message-remove\"\n data-testid=\"remove-quote\"\n (click)=\"deselectMessageToQuote()\"\n (keyup.enter)=\"deselectMessageToQuote()\"\n >\n <stream-icon-placeholder icon=\"close\"></stream-icon-placeholder>\n </button>\n </div>\n <div *ngIf=\"isUpdate\" class=\"str-chat__quoted-message-preview-header\">\n <div class=\"str-chat__quoted-message-reply-to-message\">\n {{ \"streamChat.Edit Message\" | translate }}\n </div>\n <button\n class=\"str-chat__quoted-message-remove\"\n data-testid=\"remove-quote\"\n (click)=\"deselectMessageToEdit()\"\n (keyup.enter)=\"deselectMessageToEdit()\"\n >\n <stream-icon-placeholder icon=\"close\"></stream-icon-placeholder>\n </button>\n </div>\n <ng-container *ngIf=\"canSendMessages; else notAllowed\">\n <div\n class=\"\n str-chat__message-input-inner\n str-chat-angular__message-input-inner\n \"\n >\n <ng-container\n *ngIf=\"isFileUploadEnabled && isFileUploadAuthorized && canSendMessages\"\n >\n <ng-container\n *ngTemplateOutlet=\"\n customAttachmentUploadTemplate || defaultAttachmentUpload;\n context: getAttachmentUploadContext()\n \"\n ></ng-container>\n <ng-template #defaultAttachmentUpload>\n <div\n class=\"str-chat__file-input-container\"\n data-testid=\"file-upload-button\"\n >\n <input\n #fileInput\n type=\"file\"\n class=\"str-chat__file-input\"\n data-testid=\"file-input\"\n [multiple]=\"isMultipleFileUploadEnabled\"\n id=\"{{ fileInputId }}\"\n (change)=\"filesSelected(fileInput.files)\"\n />\n <label class=\"str-chat__file-input-label\" for=\"{{ fileInputId }}\">\n <stream-icon-placeholder icon=\"attach\"></stream-icon-placeholder>\n </label>\n </div>\n </ng-template>\n </ng-container>\n <div class=\"str-chat__message-textarea-container\">\n <div\n *ngIf=\"quotedMessage\"\n data-testid=\"quoted-message-container\"\n class=\"str-chat__quoted-message-preview\"\n >\n <stream-avatar-placeholder\n data-testid=\"qouted-message-avatar\"\n class=\"\n str-chat-angular__avatar-host\n str-chat__message-sender-avatar\n \"\n type=\"user\"\n location=\"quoted-message-sender\"\n [imageUrl]=\"quotedMessage.user?.image\"\n [name]=\"quotedMessage.user?.name || quotedMessage.user?.id\"\n [user]=\"quotedMessage.user || undefined\"\n ></stream-avatar-placeholder>\n <div\n class=\"\n quoted-message-preview-content-inner\n str-chat__quoted-message-bubble\n \"\n >\n <stream-attachment-list\n *ngIf=\"\n quotedMessage?.attachments && quotedMessage?.attachments?.length\n \"\n [attachments]=\"quotedMessageAttachments\"\n [messageId]=\"quotedMessage.id\"\n ></stream-attachment-list>\n <div\n class=\"str-chat__quoted-message-text\"\n data-testid=\"quoted-message-text\"\n [innerHTML]=\"\n quotedMessage.translation ||\n quotedMessage.html ||\n quotedMessage.text\n \"\n ></div>\n </div>\n </div>\n <ng-template\n #defaultAttachmentsPreview\n let-attachmentUploads$=\"attachmentUploads$\"\n let-retryUploadHandler=\"retryUploadHandler\"\n let-deleteUploadHandler=\"deleteUploadHandler\"\n >\n <stream-attachment-preview-list\n class=\"str-chat__attachment-preview-list-angular-host\"\n [attachmentUploads$]=\"attachmentUploads$\"\n (retryAttachmentUpload)=\"retryUploadHandler($event)\"\n (deleteAttachment)=\"deleteUploadHandler($event)\"\n ></stream-attachment-preview-list>\n </ng-template>\n <ng-container\n *ngTemplateOutlet=\"\n attachmentPreviewListTemplate || defaultAttachmentsPreview;\n context: getAttachmentPreviewListContext()\n \"\n ></ng-container>\n <div class=\"str-chat__message-textarea-with-emoji-picker\">\n <ng-container\n streamTextarea\n [componentRef]=\"textareaRef\"\n [areMentionsEnabled]=\"areMentionsEnabled\"\n [mentionScope]=\"mentionScope\"\n [inputMode]=\"inputMode\"\n [autoFocus]=\"autoFocus\"\n [placeholder]=\"textareaPlaceholder\"\n [(value)]=\"textareaValue\"\n (valueChange)=\"typingStart$.next()\"\n (send)=\"messageSent()\"\n (userMentions)=\"mentionedUsers = $event\"\n ></ng-container>\n <ng-container *ngIf=\"emojiPickerTemplate\" data-testid=\"emoji-picker\">\n <ng-container\n *ngTemplateOutlet=\"\n emojiPickerTemplate;\n context: getEmojiPickerContext()\n \"\n ></ng-container>\n </ng-container>\n </div>\n </div>\n <button\n *ngIf=\"canSendMessages && !isCooldownInProgress && displaySendButton\"\n data-testid=\"send-button\"\n class=\"str-chat__send-button\"\n [disabled]=\"\n (attachmentUploadInProgressCounter$ | async)! > 0 ||\n (!textareaValue && (attachmentUploads$ | async)!.length === 0)\n \"\n (click)=\"messageSent()\"\n (keyup.enter)=\"messageSent()\"\n >\n <stream-icon-placeholder icon=\"send\"></stream-icon-placeholder>\n </button>\n <div\n *ngIf=\"isCooldownInProgress\"\n class=\"str-chat__message-input-cooldown\"\n data-testid=\"cooldown-timer\"\n >\n {{ cooldown$ | async }}\n </div>\n </div>\n </ng-container>\n <ng-template #notAllowed>\n <div\n class=\"str-chat__message-input-not-allowed\"\n data-testid=\"disabled-textarea\"\n >\n {{ disabledTextareaText | translate }}\n </div>\n </ng-template>\n</div>\n", dependencies: [{ kind: "directive", type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i4.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: AvatarPlaceholderComponent, selector: "stream-avatar-placeholder", inputs: ["name", "imageUrl", "location", "channel", "user", "type", "initialsType", "showOnlineIndicator"] }, { kind: "component", type: AttachmentListComponent, selector: "stream-attachment-list", inputs: ["messageId", "parentMessageId", "attachments"], outputs: ["imageModalStateChange"] }, { kind: "component", type: AttachmentPreviewListComponent, selector: "stream-attachment-preview-list", inputs: ["attachmentUploads$"], outputs: ["retryAttachmentUpload", "deleteAttachment"] }, { kind: "directive", type: TextareaDirective, selector: "[streamTextarea]", inputs: ["componentRef", "areMentionsEnabled", "mentionScope", "inputMode", "value", "placeholder", "autoFocus"], outputs: ["valueChange", "send", "userMentions"] }, { kind: "component", type: IconPlaceholderComponent, selector: "stream-icon-placeholder", inputs: ["icon"] }, { kind: "pipe", type: i4.AsyncPipe, name: "async" }, { kind: "pipe", type: i10.TranslatePipe, name: "translate" }] });
6079
+ MessageInputComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.0.4", type: MessageInputComponent, selector: "stream-message-input", inputs: { isFileUploadEnabled: "isFileUploadEnabled", areMentionsEnabled: "areMentionsEnabled", mentionScope: "mentionScope", mode: "mode", isMultipleFileUploadEnabled: "isMultipleFileUploadEnabled", message: "message", sendMessage$: "sendMessage$", inputMode: "inputMode", autoFocus: "autoFocus", watchForMessageToEdit: "watchForMessageToEdit", displaySendButton: "displaySendButton" }, outputs: { messageUpdate: "messageUpdate" }, host: { properties: { "class": "this.class" } }, providers: [AttachmentService, EmojiInputService], viewQueries: [{ propertyName: "fileInput", first: true, predicate: ["fileInput"], descendants: true }, { propertyName: "textareaAnchor", first: true, predicate: TextareaDirective, descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div class=\"str-chat__message-input str-chat-angular__message-input\">\n <div *ngIf=\"quotedMessage\" class=\"str-chat__quoted-message-preview-header\">\n <div class=\"str-chat__quoted-message-reply-to-message\">\n {{ \"streamChat.Reply to Message\" | translate }}\n </div>\n <button\n class=\"str-chat__quoted-message-remove\"\n data-testid=\"remove-quote\"\n (click)=\"deselectMessageToQuote()\"\n (keyup.enter)=\"deselectMessageToQuote()\"\n >\n <stream-icon-placeholder icon=\"close\"></stream-icon-placeholder>\n </button>\n </div>\n <div *ngIf=\"isUpdate\" class=\"str-chat__quoted-message-preview-header\">\n <div class=\"str-chat__quoted-message-reply-to-message\">\n {{ \"streamChat.Edit Message\" | translate }}\n </div>\n <button\n class=\"str-chat__quoted-message-remove\"\n data-testid=\"remove-quote\"\n (click)=\"deselectMessageToEdit()\"\n (keyup.enter)=\"deselectMessageToEdit()\"\n >\n <stream-icon-placeholder icon=\"close\"></stream-icon-placeholder>\n </button>\n </div>\n <ng-container *ngIf=\"canSendMessages; else notAllowed\">\n <div\n class=\"str-chat__message-input-inner str-chat-angular__message-input-inner\"\n >\n <ng-container\n *ngIf=\"isFileUploadEnabled && isFileUploadAuthorized && canSendMessages\"\n >\n <ng-container\n *ngTemplateOutlet=\"\n customAttachmentUploadTemplate || defaultAttachmentUpload;\n context: getAttachmentUploadContext()\n \"\n ></ng-container>\n <ng-template #defaultAttachmentUpload>\n <div\n class=\"str-chat__file-input-container\"\n data-testid=\"file-upload-button\"\n >\n <input\n #fileInput\n type=\"file\"\n class=\"str-chat__file-input\"\n data-testid=\"file-input\"\n [multiple]=\"isMultipleFileUploadEnabled\"\n id=\"{{ fileInputId }}\"\n (change)=\"filesSelected(fileInput.files)\"\n />\n <label class=\"str-chat__file-input-label\" for=\"{{ fileInputId }}\">\n <stream-icon-placeholder icon=\"attach\"></stream-icon-placeholder>\n </label>\n </div>\n </ng-template>\n </ng-container>\n <div class=\"str-chat__message-textarea-container\">\n <div\n *ngIf=\"quotedMessage\"\n data-testid=\"quoted-message-container\"\n class=\"str-chat__quoted-message-preview\"\n >\n <stream-avatar-placeholder\n data-testid=\"qouted-message-avatar\"\n class=\"str-chat-angular__avatar-host str-chat__message-sender-avatar\"\n type=\"user\"\n location=\"quoted-message-sender\"\n [imageUrl]=\"quotedMessage.user?.image\"\n [name]=\"quotedMessage.user?.name || quotedMessage.user?.id\"\n [user]=\"quotedMessage.user || undefined\"\n ></stream-avatar-placeholder>\n <div\n class=\"quoted-message-preview-content-inner str-chat__quoted-message-bubble\"\n >\n <stream-attachment-list\n *ngIf=\"\n quotedMessage?.attachments && quotedMessage?.attachments?.length\n \"\n [attachments]=\"quotedMessageAttachments\"\n [messageId]=\"quotedMessage.id\"\n ></stream-attachment-list>\n <div\n class=\"str-chat__quoted-message-text\"\n data-testid=\"quoted-message-text\"\n [innerHTML]=\"\n quotedMessage.translation ||\n quotedMessage.html ||\n quotedMessage.text\n \"\n ></div>\n </div>\n </div>\n <ng-template\n #defaultAttachmentsPreview\n let-attachmentUploads$=\"attachmentUploads$\"\n let-retryUploadHandler=\"retryUploadHandler\"\n let-deleteUploadHandler=\"deleteUploadHandler\"\n >\n <stream-attachment-preview-list\n class=\"str-chat__attachment-preview-list-angular-host\"\n [attachmentUploads$]=\"attachmentUploads$\"\n (retryAttachmentUpload)=\"retryUploadHandler($event)\"\n (deleteAttachment)=\"deleteUploadHandler($event)\"\n ></stream-attachment-preview-list>\n </ng-template>\n <ng-container\n *ngTemplateOutlet=\"\n attachmentPreviewListTemplate || defaultAttachmentsPreview;\n context: getAttachmentPreviewListContext()\n \"\n ></ng-container>\n <div class=\"str-chat__message-textarea-with-emoji-picker\">\n <ng-container\n streamTextarea\n [componentRef]=\"textareaRef\"\n [areMentionsEnabled]=\"areMentionsEnabled\"\n [mentionScope]=\"mentionScope\"\n [inputMode]=\"inputMode\"\n [autoFocus]=\"autoFocus\"\n [placeholder]=\"textareaPlaceholder\"\n [(value)]=\"textareaValue\"\n (valueChange)=\"typingStart$.next()\"\n (send)=\"messageSent()\"\n (userMentions)=\"mentionedUsers = $event\"\n ></ng-container>\n <ng-container *ngIf=\"emojiPickerTemplate\" data-testid=\"emoji-picker\">\n <ng-container\n *ngTemplateOutlet=\"\n emojiPickerTemplate;\n context: getEmojiPickerContext()\n \"\n ></ng-container>\n </ng-container>\n </div>\n </div>\n <button\n *ngIf=\"canSendMessages && !isCooldownInProgress && displaySendButton\"\n data-testid=\"send-button\"\n class=\"str-chat__send-button\"\n [disabled]=\"\n (attachmentUploadInProgressCounter$ | async)! > 0 ||\n (!textareaValue && (attachmentUploads$ | async)!.length === 0)\n \"\n (click)=\"messageSent()\"\n (keyup.enter)=\"messageSent()\"\n >\n <stream-icon-placeholder icon=\"send\"></stream-icon-placeholder>\n </button>\n <div\n *ngIf=\"isCooldownInProgress\"\n class=\"str-chat__message-input-cooldown\"\n data-testid=\"cooldown-timer\"\n >\n {{ cooldown$ | async }}\n </div>\n </div>\n </ng-container>\n <ng-template #notAllowed>\n <div\n class=\"str-chat__message-input-not-allowed\"\n data-testid=\"disabled-textarea\"\n >\n {{ disabledTextareaText | translate }}\n </div>\n </ng-template>\n</div>\n", dependencies: [{ kind: "directive", type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i4.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: AvatarPlaceholderComponent, selector: "stream-avatar-placeholder", inputs: ["name", "imageUrl", "location", "channel", "user", "type", "initialsType", "showOnlineIndicator"] }, { kind: "component", type: AttachmentListComponent, selector: "stream-attachment-list", inputs: ["messageId", "parentMessageId", "attachments"], outputs: ["imageModalStateChange"] }, { kind: "component", type: AttachmentPreviewListComponent, selector: "stream-attachment-preview-list", inputs: ["attachmentUploads$"], outputs: ["retryAttachmentUpload", "deleteAttachment"] }, { kind: "directive", type: TextareaDirective, selector: "[streamTextarea]", inputs: ["componentRef", "areMentionsEnabled", "mentionScope", "inputMode", "value", "placeholder", "autoFocus"], outputs: ["valueChange", "send", "userMentions"] }, { kind: "component", type: IconPlaceholderComponent, selector: "stream-icon-placeholder", inputs: ["icon"] }, { kind: "pipe", type: i4.AsyncPipe, name: "async" }, { kind: "pipe", type: i10.TranslatePipe, name: "translate" }] });
5914
6080
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.4", ngImport: i0, type: MessageInputComponent, decorators: [{
5915
6081
  type: Component,
5916
- args: [{ selector: 'stream-message-input', providers: [AttachmentService, EmojiInputService], template: "<div class=\"str-chat__message-input str-chat-angular__message-input\">\n <div *ngIf=\"quotedMessage\" class=\"str-chat__quoted-message-preview-header\">\n <div class=\"str-chat__quoted-message-reply-to-message\">\n {{ \"streamChat.Reply to Message\" | translate }}\n </div>\n <button\n class=\"str-chat__quoted-message-remove\"\n data-testid=\"remove-quote\"\n (click)=\"deselectMessageToQuote()\"\n (keyup.enter)=\"deselectMessageToQuote()\"\n >\n <stream-icon-placeholder icon=\"close\"></stream-icon-placeholder>\n </button>\n </div>\n <div *ngIf=\"isUpdate\" class=\"str-chat__quoted-message-preview-header\">\n <div class=\"str-chat__quoted-message-reply-to-message\">\n {{ \"streamChat.Edit Message\" | translate }}\n </div>\n <button\n class=\"str-chat__quoted-message-remove\"\n data-testid=\"remove-quote\"\n (click)=\"deselectMessageToEdit()\"\n (keyup.enter)=\"deselectMessageToEdit()\"\n >\n <stream-icon-placeholder icon=\"close\"></stream-icon-placeholder>\n </button>\n </div>\n <ng-container *ngIf=\"canSendMessages; else notAllowed\">\n <div\n class=\"\n str-chat__message-input-inner\n str-chat-angular__message-input-inner\n \"\n >\n <ng-container\n *ngIf=\"isFileUploadEnabled && isFileUploadAuthorized && canSendMessages\"\n >\n <ng-container\n *ngTemplateOutlet=\"\n customAttachmentUploadTemplate || defaultAttachmentUpload;\n context: getAttachmentUploadContext()\n \"\n ></ng-container>\n <ng-template #defaultAttachmentUpload>\n <div\n class=\"str-chat__file-input-container\"\n data-testid=\"file-upload-button\"\n >\n <input\n #fileInput\n type=\"file\"\n class=\"str-chat__file-input\"\n data-testid=\"file-input\"\n [multiple]=\"isMultipleFileUploadEnabled\"\n id=\"{{ fileInputId }}\"\n (change)=\"filesSelected(fileInput.files)\"\n />\n <label class=\"str-chat__file-input-label\" for=\"{{ fileInputId }}\">\n <stream-icon-placeholder icon=\"attach\"></stream-icon-placeholder>\n </label>\n </div>\n </ng-template>\n </ng-container>\n <div class=\"str-chat__message-textarea-container\">\n <div\n *ngIf=\"quotedMessage\"\n data-testid=\"quoted-message-container\"\n class=\"str-chat__quoted-message-preview\"\n >\n <stream-avatar-placeholder\n data-testid=\"qouted-message-avatar\"\n class=\"\n str-chat-angular__avatar-host\n str-chat__message-sender-avatar\n \"\n type=\"user\"\n location=\"quoted-message-sender\"\n [imageUrl]=\"quotedMessage.user?.image\"\n [name]=\"quotedMessage.user?.name || quotedMessage.user?.id\"\n [user]=\"quotedMessage.user || undefined\"\n ></stream-avatar-placeholder>\n <div\n class=\"\n quoted-message-preview-content-inner\n str-chat__quoted-message-bubble\n \"\n >\n <stream-attachment-list\n *ngIf=\"\n quotedMessage?.attachments && quotedMessage?.attachments?.length\n \"\n [attachments]=\"quotedMessageAttachments\"\n [messageId]=\"quotedMessage.id\"\n ></stream-attachment-list>\n <div\n class=\"str-chat__quoted-message-text\"\n data-testid=\"quoted-message-text\"\n [innerHTML]=\"\n quotedMessage.translation ||\n quotedMessage.html ||\n quotedMessage.text\n \"\n ></div>\n </div>\n </div>\n <ng-template\n #defaultAttachmentsPreview\n let-attachmentUploads$=\"attachmentUploads$\"\n let-retryUploadHandler=\"retryUploadHandler\"\n let-deleteUploadHandler=\"deleteUploadHandler\"\n >\n <stream-attachment-preview-list\n class=\"str-chat__attachment-preview-list-angular-host\"\n [attachmentUploads$]=\"attachmentUploads$\"\n (retryAttachmentUpload)=\"retryUploadHandler($event)\"\n (deleteAttachment)=\"deleteUploadHandler($event)\"\n ></stream-attachment-preview-list>\n </ng-template>\n <ng-container\n *ngTemplateOutlet=\"\n attachmentPreviewListTemplate || defaultAttachmentsPreview;\n context: getAttachmentPreviewListContext()\n \"\n ></ng-container>\n <div class=\"str-chat__message-textarea-with-emoji-picker\">\n <ng-container\n streamTextarea\n [componentRef]=\"textareaRef\"\n [areMentionsEnabled]=\"areMentionsEnabled\"\n [mentionScope]=\"mentionScope\"\n [inputMode]=\"inputMode\"\n [autoFocus]=\"autoFocus\"\n [placeholder]=\"textareaPlaceholder\"\n [(value)]=\"textareaValue\"\n (valueChange)=\"typingStart$.next()\"\n (send)=\"messageSent()\"\n (userMentions)=\"mentionedUsers = $event\"\n ></ng-container>\n <ng-container *ngIf=\"emojiPickerTemplate\" data-testid=\"emoji-picker\">\n <ng-container\n *ngTemplateOutlet=\"\n emojiPickerTemplate;\n context: getEmojiPickerContext()\n \"\n ></ng-container>\n </ng-container>\n </div>\n </div>\n <button\n *ngIf=\"canSendMessages && !isCooldownInProgress && displaySendButton\"\n data-testid=\"send-button\"\n class=\"str-chat__send-button\"\n [disabled]=\"\n (attachmentUploadInProgressCounter$ | async)! > 0 ||\n (!textareaValue && (attachmentUploads$ | async)!.length === 0)\n \"\n (click)=\"messageSent()\"\n (keyup.enter)=\"messageSent()\"\n >\n <stream-icon-placeholder icon=\"send\"></stream-icon-placeholder>\n </button>\n <div\n *ngIf=\"isCooldownInProgress\"\n class=\"str-chat__message-input-cooldown\"\n data-testid=\"cooldown-timer\"\n >\n {{ cooldown$ | async }}\n </div>\n </div>\n </ng-container>\n <ng-template #notAllowed>\n <div\n class=\"str-chat__message-input-not-allowed\"\n data-testid=\"disabled-textarea\"\n >\n {{ disabledTextareaText | translate }}\n </div>\n </ng-template>\n</div>\n" }]
6082
+ args: [{ selector: 'stream-message-input', providers: [AttachmentService, EmojiInputService], template: "<div class=\"str-chat__message-input str-chat-angular__message-input\">\n <div *ngIf=\"quotedMessage\" class=\"str-chat__quoted-message-preview-header\">\n <div class=\"str-chat__quoted-message-reply-to-message\">\n {{ \"streamChat.Reply to Message\" | translate }}\n </div>\n <button\n class=\"str-chat__quoted-message-remove\"\n data-testid=\"remove-quote\"\n (click)=\"deselectMessageToQuote()\"\n (keyup.enter)=\"deselectMessageToQuote()\"\n >\n <stream-icon-placeholder icon=\"close\"></stream-icon-placeholder>\n </button>\n </div>\n <div *ngIf=\"isUpdate\" class=\"str-chat__quoted-message-preview-header\">\n <div class=\"str-chat__quoted-message-reply-to-message\">\n {{ \"streamChat.Edit Message\" | translate }}\n </div>\n <button\n class=\"str-chat__quoted-message-remove\"\n data-testid=\"remove-quote\"\n (click)=\"deselectMessageToEdit()\"\n (keyup.enter)=\"deselectMessageToEdit()\"\n >\n <stream-icon-placeholder icon=\"close\"></stream-icon-placeholder>\n </button>\n </div>\n <ng-container *ngIf=\"canSendMessages; else notAllowed\">\n <div\n class=\"str-chat__message-input-inner str-chat-angular__message-input-inner\"\n >\n <ng-container\n *ngIf=\"isFileUploadEnabled && isFileUploadAuthorized && canSendMessages\"\n >\n <ng-container\n *ngTemplateOutlet=\"\n customAttachmentUploadTemplate || defaultAttachmentUpload;\n context: getAttachmentUploadContext()\n \"\n ></ng-container>\n <ng-template #defaultAttachmentUpload>\n <div\n class=\"str-chat__file-input-container\"\n data-testid=\"file-upload-button\"\n >\n <input\n #fileInput\n type=\"file\"\n class=\"str-chat__file-input\"\n data-testid=\"file-input\"\n [multiple]=\"isMultipleFileUploadEnabled\"\n id=\"{{ fileInputId }}\"\n (change)=\"filesSelected(fileInput.files)\"\n />\n <label class=\"str-chat__file-input-label\" for=\"{{ fileInputId }}\">\n <stream-icon-placeholder icon=\"attach\"></stream-icon-placeholder>\n </label>\n </div>\n </ng-template>\n </ng-container>\n <div class=\"str-chat__message-textarea-container\">\n <div\n *ngIf=\"quotedMessage\"\n data-testid=\"quoted-message-container\"\n class=\"str-chat__quoted-message-preview\"\n >\n <stream-avatar-placeholder\n data-testid=\"qouted-message-avatar\"\n class=\"str-chat-angular__avatar-host str-chat__message-sender-avatar\"\n type=\"user\"\n location=\"quoted-message-sender\"\n [imageUrl]=\"quotedMessage.user?.image\"\n [name]=\"quotedMessage.user?.name || quotedMessage.user?.id\"\n [user]=\"quotedMessage.user || undefined\"\n ></stream-avatar-placeholder>\n <div\n class=\"quoted-message-preview-content-inner str-chat__quoted-message-bubble\"\n >\n <stream-attachment-list\n *ngIf=\"\n quotedMessage?.attachments && quotedMessage?.attachments?.length\n \"\n [attachments]=\"quotedMessageAttachments\"\n [messageId]=\"quotedMessage.id\"\n ></stream-attachment-list>\n <div\n class=\"str-chat__quoted-message-text\"\n data-testid=\"quoted-message-text\"\n [innerHTML]=\"\n quotedMessage.translation ||\n quotedMessage.html ||\n quotedMessage.text\n \"\n ></div>\n </div>\n </div>\n <ng-template\n #defaultAttachmentsPreview\n let-attachmentUploads$=\"attachmentUploads$\"\n let-retryUploadHandler=\"retryUploadHandler\"\n let-deleteUploadHandler=\"deleteUploadHandler\"\n >\n <stream-attachment-preview-list\n class=\"str-chat__attachment-preview-list-angular-host\"\n [attachmentUploads$]=\"attachmentUploads$\"\n (retryAttachmentUpload)=\"retryUploadHandler($event)\"\n (deleteAttachment)=\"deleteUploadHandler($event)\"\n ></stream-attachment-preview-list>\n </ng-template>\n <ng-container\n *ngTemplateOutlet=\"\n attachmentPreviewListTemplate || defaultAttachmentsPreview;\n context: getAttachmentPreviewListContext()\n \"\n ></ng-container>\n <div class=\"str-chat__message-textarea-with-emoji-picker\">\n <ng-container\n streamTextarea\n [componentRef]=\"textareaRef\"\n [areMentionsEnabled]=\"areMentionsEnabled\"\n [mentionScope]=\"mentionScope\"\n [inputMode]=\"inputMode\"\n [autoFocus]=\"autoFocus\"\n [placeholder]=\"textareaPlaceholder\"\n [(value)]=\"textareaValue\"\n (valueChange)=\"typingStart$.next()\"\n (send)=\"messageSent()\"\n (userMentions)=\"mentionedUsers = $event\"\n ></ng-container>\n <ng-container *ngIf=\"emojiPickerTemplate\" data-testid=\"emoji-picker\">\n <ng-container\n *ngTemplateOutlet=\"\n emojiPickerTemplate;\n context: getEmojiPickerContext()\n \"\n ></ng-container>\n </ng-container>\n </div>\n </div>\n <button\n *ngIf=\"canSendMessages && !isCooldownInProgress && displaySendButton\"\n data-testid=\"send-button\"\n class=\"str-chat__send-button\"\n [disabled]=\"\n (attachmentUploadInProgressCounter$ | async)! > 0 ||\n (!textareaValue && (attachmentUploads$ | async)!.length === 0)\n \"\n (click)=\"messageSent()\"\n (keyup.enter)=\"messageSent()\"\n >\n <stream-icon-placeholder icon=\"send\"></stream-icon-placeholder>\n </button>\n <div\n *ngIf=\"isCooldownInProgress\"\n class=\"str-chat__message-input-cooldown\"\n data-testid=\"cooldown-timer\"\n >\n {{ cooldown$ | async }}\n </div>\n </div>\n </ng-container>\n <ng-template #notAllowed>\n <div\n class=\"str-chat__message-input-not-allowed\"\n data-testid=\"disabled-textarea\"\n >\n {{ disabledTextareaText | translate }}\n </div>\n </ng-template>\n</div>\n" }]
5917
6083
  }], ctorParameters: function () {
5918
6084
  return [{ type: ChannelService }, { type: NotificationService }, { type: AttachmentService }, { type: MessageInputConfigService }, { type: i0.Type, decorators: [{
5919
6085
  type: Inject,
@@ -6034,10 +6200,10 @@ class TextareaComponent {
6034
6200
  }
6035
6201
  }
6036
6202
  TextareaComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.4", ngImport: i0, type: TextareaComponent, deps: [{ token: EmojiInputService }, { token: ThemeService }], target: i0.ɵɵFactoryTarget.Component });
6037
- TextareaComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.0.4", type: TextareaComponent, selector: "stream-textarea", inputs: { value: "value", placeholder: "placeholder", inputMode: "inputMode", autoFocus: "autoFocus" }, outputs: { valueChange: "valueChange", send: "send" }, host: { properties: { "class": "this.class" } }, viewQueries: [{ propertyName: "messageInput", first: true, predicate: ["input"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<textarea\n #input\n data-testid=\"textarea\"\n class=\"\n rta__textarea\n str-chat__textarea__textarea\n str-chat__angular-textarea\n str-chat__message-textarea\n \"\n rows=\"1\"\n [value]=\"value || ''\"\n [autofocus]=\"autoFocus\"\n placeholder=\"{{ placeholder | translate }}\"\n (input)=\"inputChanged()\"\n (keydown.enter)=\"enterHit($event)\"\n></textarea>\n", dependencies: [{ kind: "pipe", type: i10.TranslatePipe, name: "translate" }] });
6203
+ TextareaComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.0.4", type: TextareaComponent, selector: "stream-textarea", inputs: { value: "value", placeholder: "placeholder", inputMode: "inputMode", autoFocus: "autoFocus" }, outputs: { valueChange: "valueChange", send: "send" }, host: { properties: { "class": "this.class" } }, viewQueries: [{ propertyName: "messageInput", first: true, predicate: ["input"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<textarea\n #input\n data-testid=\"textarea\"\n class=\"rta__textarea str-chat__textarea__textarea str-chat__angular-textarea str-chat__message-textarea\"\n rows=\"1\"\n [value]=\"value || ''\"\n [autofocus]=\"autoFocus\"\n placeholder=\"{{ placeholder | translate }}\"\n (input)=\"inputChanged()\"\n (keydown.enter)=\"enterHit($event)\"\n></textarea>\n", dependencies: [{ kind: "pipe", type: i10.TranslatePipe, name: "translate" }] });
6038
6204
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.4", ngImport: i0, type: TextareaComponent, decorators: [{
6039
6205
  type: Component,
6040
- args: [{ selector: 'stream-textarea', template: "<textarea\n #input\n data-testid=\"textarea\"\n class=\"\n rta__textarea\n str-chat__textarea__textarea\n str-chat__angular-textarea\n str-chat__message-textarea\n \"\n rows=\"1\"\n [value]=\"value || ''\"\n [autofocus]=\"autoFocus\"\n placeholder=\"{{ placeholder | translate }}\"\n (input)=\"inputChanged()\"\n (keydown.enter)=\"enterHit($event)\"\n></textarea>\n" }]
6206
+ args: [{ selector: 'stream-textarea', template: "<textarea\n #input\n data-testid=\"textarea\"\n class=\"rta__textarea str-chat__textarea__textarea str-chat__angular-textarea str-chat__message-textarea\"\n rows=\"1\"\n [value]=\"value || ''\"\n [autofocus]=\"autoFocus\"\n placeholder=\"{{ placeholder | translate }}\"\n (input)=\"inputChanged()\"\n (keydown.enter)=\"enterHit($event)\"\n></textarea>\n" }]
6041
6207
  }], ctorParameters: function () { return [{ type: EmojiInputService }, { type: ThemeService }]; }, propDecorators: { class: [{
6042
6208
  type: HostBinding
6043
6209
  }], value: [{
@@ -6308,10 +6474,10 @@ class AutocompleteTextareaComponent {
6308
6474
  }
6309
6475
  }
6310
6476
  AutocompleteTextareaComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.4", ngImport: i0, type: AutocompleteTextareaComponent, deps: [{ token: ChannelService }, { token: ChatClientService }, { token: TransliterationService }, { token: EmojiInputService }, { token: CustomTemplatesService }, { token: ThemeService }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
6311
- AutocompleteTextareaComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.0.4", type: AutocompleteTextareaComponent, selector: "stream-autocomplete-textarea", inputs: { value: "value", placeholder: "placeholder", areMentionsEnabled: "areMentionsEnabled", inputMode: "inputMode", mentionScope: "mentionScope", autoFocus: "autoFocus" }, outputs: { valueChange: "valueChange", send: "send", userMentions: "userMentions" }, host: { properties: { "class": "this.class" } }, viewQueries: [{ propertyName: "messageInput", first: true, predicate: ["input"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<textarea\n #input\n data-testid=\"textarea\"\n class=\"\n rta__textarea\n str-chat__textarea__textarea\n str-chat__angular-textarea\n str-chat__message-textarea\n \"\n rows=\"1\"\n [value]=\"value || ''\"\n [autofocus]=\"autoFocus\"\n placeholder=\"{{ placeholder | translate }}\"\n [mentionConfig]=\"autocompleteConfig\"\n [mentionListTemplate]=\"autocompleteItem\"\n (input)=\"inputChanged()\"\n (keydown.enter)=\"enterHit($event)\"\n (searchTerm)=\"autcompleteSearchTermChanged($event)\"\n (blur)=\"inputLeft()\"\n></textarea>\n<ng-template #autocompleteItem let-item=\"item\">\n <div class=\"rta rta__item str-chat__emojisearch__item\" [ngSwitch]=\"item.type\">\n <div *ngSwitchCase=\"'mention'\" class=\"rta__entity\">\n <ng-container\n *ngTemplateOutlet=\"\n mentionAutocompleteItemTemplate || defaultMentionTemplate;\n context: { item: item }\n \"\n ></ng-container>\n </div>\n <div *ngSwitchCase=\"'command'\" class=\"rta__entity\">\n <ng-container\n *ngTemplateOutlet=\"\n commandAutocompleteItemTemplate || defaultCommandTemplate;\n context: { item: item }\n \"\n ></ng-container>\n </div>\n </div>\n</ng-template>\n\n<ng-template #defaultCommandTemplate let-item=\"item\">\n <div class=\"str-chat__slash-command\">\n <span class=\"str-chat__slash-command-header\">\n <strong\n class=\"str-chat__slash-command-name\"\n data-testclass=\"command-name\"\n >{{ item.name }}</strong\n >\n <span class=\"str-chat__slash-command-args\"\n >/{{ item.name }} {{ item.args }}</span\n >\n </span>\n <br />\n </div>\n</ng-template>\n\n<ng-template #defaultMentionTemplate let-item=\"item\">\n <div class=\"str-chat__user-item\">\n <stream-avatar-placeholder\n data-testclass=\"avatar\"\n class=\"str-chat__avatar str-chat__avatar--circle\"\n type=\"user\"\n location=\"autocomplete-item\"\n [imageUrl]=\"item.image || item.user?.image\"\n [name]=\"item.autocompleteLabel\"\n [user]=\"item.user || item\"\n ></stream-avatar-placeholder>\n <span data-testclass=\"username\" class=\"str-chat__user-item--name\">{{\n item.autocompleteLabel\n }}</span>\n </div>\n</ng-template>\n", dependencies: [{ kind: "directive", type: i4.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i4.NgSwitch, selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { kind: "directive", type: i4.NgSwitchCase, selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }, { kind: "directive", type: i8$1.MentionDirective, selector: "[mention], [mentionConfig]", inputs: ["mentionConfig", "mention", "mentionListTemplate"], outputs: ["searchTerm", "itemSelected", "opened", "closed"] }, { kind: "component", type: AvatarPlaceholderComponent, selector: "stream-avatar-placeholder", inputs: ["name", "imageUrl", "location", "channel", "user", "type", "initialsType", "showOnlineIndicator"] }, { kind: "pipe", type: i10.TranslatePipe, name: "translate" }] });
6477
+ AutocompleteTextareaComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.0.4", type: AutocompleteTextareaComponent, selector: "stream-autocomplete-textarea", inputs: { value: "value", placeholder: "placeholder", areMentionsEnabled: "areMentionsEnabled", inputMode: "inputMode", mentionScope: "mentionScope", autoFocus: "autoFocus" }, outputs: { valueChange: "valueChange", send: "send", userMentions: "userMentions" }, host: { properties: { "class": "this.class" } }, viewQueries: [{ propertyName: "messageInput", first: true, predicate: ["input"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<textarea\n #input\n data-testid=\"textarea\"\n class=\"rta__textarea str-chat__textarea__textarea str-chat__angular-textarea str-chat__message-textarea\"\n rows=\"1\"\n [value]=\"value || ''\"\n [autofocus]=\"autoFocus\"\n placeholder=\"{{ placeholder | translate }}\"\n [mentionConfig]=\"autocompleteConfig\"\n [mentionListTemplate]=\"autocompleteItem\"\n (input)=\"inputChanged()\"\n (keydown.enter)=\"enterHit($event)\"\n (searchTerm)=\"autcompleteSearchTermChanged($event)\"\n (blur)=\"inputLeft()\"\n></textarea>\n<ng-template #autocompleteItem let-item=\"item\">\n <div class=\"rta rta__item str-chat__emojisearch__item\" [ngSwitch]=\"item.type\">\n <div *ngSwitchCase=\"'mention'\" class=\"rta__entity\">\n <ng-container\n *ngTemplateOutlet=\"\n mentionAutocompleteItemTemplate || defaultMentionTemplate;\n context: { item: item }\n \"\n ></ng-container>\n </div>\n <div *ngSwitchCase=\"'command'\" class=\"rta__entity\">\n <ng-container\n *ngTemplateOutlet=\"\n commandAutocompleteItemTemplate || defaultCommandTemplate;\n context: { item: item }\n \"\n ></ng-container>\n </div>\n </div>\n</ng-template>\n\n<ng-template #defaultCommandTemplate let-item=\"item\">\n <div class=\"str-chat__slash-command\">\n <span class=\"str-chat__slash-command-header\">\n <strong\n class=\"str-chat__slash-command-name\"\n data-testclass=\"command-name\"\n >{{ item.name }}</strong\n >\n <span class=\"str-chat__slash-command-args\"\n >/{{ item.name }} {{ item.args }}</span\n >\n </span>\n <br />\n </div>\n</ng-template>\n\n<ng-template #defaultMentionTemplate let-item=\"item\">\n <div class=\"str-chat__user-item\">\n <stream-avatar-placeholder\n data-testclass=\"avatar\"\n class=\"str-chat__avatar str-chat__avatar--circle\"\n type=\"user\"\n location=\"autocomplete-item\"\n [imageUrl]=\"item.image || item.user?.image\"\n [name]=\"item.autocompleteLabel\"\n [user]=\"item.user || item\"\n ></stream-avatar-placeholder>\n <span data-testclass=\"username\" class=\"str-chat__user-item--name\">{{\n item.autocompleteLabel\n }}</span>\n </div>\n</ng-template>\n", dependencies: [{ kind: "directive", type: i4.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i4.NgSwitch, selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { kind: "directive", type: i4.NgSwitchCase, selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }, { kind: "directive", type: i8$1.MentionDirective, selector: "[mention], [mentionConfig]", inputs: ["mentionConfig", "mention", "mentionListTemplate"], outputs: ["searchTerm", "itemSelected", "opened", "closed"] }, { kind: "component", type: AvatarPlaceholderComponent, selector: "stream-avatar-placeholder", inputs: ["name", "imageUrl", "location", "channel", "user", "type", "initialsType", "showOnlineIndicator"] }, { kind: "pipe", type: i10.TranslatePipe, name: "translate" }] });
6312
6478
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.4", ngImport: i0, type: AutocompleteTextareaComponent, decorators: [{
6313
6479
  type: Component,
6314
- args: [{ selector: 'stream-autocomplete-textarea', template: "<textarea\n #input\n data-testid=\"textarea\"\n class=\"\n rta__textarea\n str-chat__textarea__textarea\n str-chat__angular-textarea\n str-chat__message-textarea\n \"\n rows=\"1\"\n [value]=\"value || ''\"\n [autofocus]=\"autoFocus\"\n placeholder=\"{{ placeholder | translate }}\"\n [mentionConfig]=\"autocompleteConfig\"\n [mentionListTemplate]=\"autocompleteItem\"\n (input)=\"inputChanged()\"\n (keydown.enter)=\"enterHit($event)\"\n (searchTerm)=\"autcompleteSearchTermChanged($event)\"\n (blur)=\"inputLeft()\"\n></textarea>\n<ng-template #autocompleteItem let-item=\"item\">\n <div class=\"rta rta__item str-chat__emojisearch__item\" [ngSwitch]=\"item.type\">\n <div *ngSwitchCase=\"'mention'\" class=\"rta__entity\">\n <ng-container\n *ngTemplateOutlet=\"\n mentionAutocompleteItemTemplate || defaultMentionTemplate;\n context: { item: item }\n \"\n ></ng-container>\n </div>\n <div *ngSwitchCase=\"'command'\" class=\"rta__entity\">\n <ng-container\n *ngTemplateOutlet=\"\n commandAutocompleteItemTemplate || defaultCommandTemplate;\n context: { item: item }\n \"\n ></ng-container>\n </div>\n </div>\n</ng-template>\n\n<ng-template #defaultCommandTemplate let-item=\"item\">\n <div class=\"str-chat__slash-command\">\n <span class=\"str-chat__slash-command-header\">\n <strong\n class=\"str-chat__slash-command-name\"\n data-testclass=\"command-name\"\n >{{ item.name }}</strong\n >\n <span class=\"str-chat__slash-command-args\"\n >/{{ item.name }} {{ item.args }}</span\n >\n </span>\n <br />\n </div>\n</ng-template>\n\n<ng-template #defaultMentionTemplate let-item=\"item\">\n <div class=\"str-chat__user-item\">\n <stream-avatar-placeholder\n data-testclass=\"avatar\"\n class=\"str-chat__avatar str-chat__avatar--circle\"\n type=\"user\"\n location=\"autocomplete-item\"\n [imageUrl]=\"item.image || item.user?.image\"\n [name]=\"item.autocompleteLabel\"\n [user]=\"item.user || item\"\n ></stream-avatar-placeholder>\n <span data-testclass=\"username\" class=\"str-chat__user-item--name\">{{\n item.autocompleteLabel\n }}</span>\n </div>\n</ng-template>\n" }]
6480
+ args: [{ selector: 'stream-autocomplete-textarea', template: "<textarea\n #input\n data-testid=\"textarea\"\n class=\"rta__textarea str-chat__textarea__textarea str-chat__angular-textarea str-chat__message-textarea\"\n rows=\"1\"\n [value]=\"value || ''\"\n [autofocus]=\"autoFocus\"\n placeholder=\"{{ placeholder | translate }}\"\n [mentionConfig]=\"autocompleteConfig\"\n [mentionListTemplate]=\"autocompleteItem\"\n (input)=\"inputChanged()\"\n (keydown.enter)=\"enterHit($event)\"\n (searchTerm)=\"autcompleteSearchTermChanged($event)\"\n (blur)=\"inputLeft()\"\n></textarea>\n<ng-template #autocompleteItem let-item=\"item\">\n <div class=\"rta rta__item str-chat__emojisearch__item\" [ngSwitch]=\"item.type\">\n <div *ngSwitchCase=\"'mention'\" class=\"rta__entity\">\n <ng-container\n *ngTemplateOutlet=\"\n mentionAutocompleteItemTemplate || defaultMentionTemplate;\n context: { item: item }\n \"\n ></ng-container>\n </div>\n <div *ngSwitchCase=\"'command'\" class=\"rta__entity\">\n <ng-container\n *ngTemplateOutlet=\"\n commandAutocompleteItemTemplate || defaultCommandTemplate;\n context: { item: item }\n \"\n ></ng-container>\n </div>\n </div>\n</ng-template>\n\n<ng-template #defaultCommandTemplate let-item=\"item\">\n <div class=\"str-chat__slash-command\">\n <span class=\"str-chat__slash-command-header\">\n <strong\n class=\"str-chat__slash-command-name\"\n data-testclass=\"command-name\"\n >{{ item.name }}</strong\n >\n <span class=\"str-chat__slash-command-args\"\n >/{{ item.name }} {{ item.args }}</span\n >\n </span>\n <br />\n </div>\n</ng-template>\n\n<ng-template #defaultMentionTemplate let-item=\"item\">\n <div class=\"str-chat__user-item\">\n <stream-avatar-placeholder\n data-testclass=\"avatar\"\n class=\"str-chat__avatar str-chat__avatar--circle\"\n type=\"user\"\n location=\"autocomplete-item\"\n [imageUrl]=\"item.image || item.user?.image\"\n [name]=\"item.autocompleteLabel\"\n [user]=\"item.user || item\"\n ></stream-avatar-placeholder>\n <span data-testclass=\"username\" class=\"str-chat__user-item--name\">{{\n item.autocompleteLabel\n }}</span>\n </div>\n</ng-template>\n" }]
6315
6481
  }], ctorParameters: function () { return [{ type: ChannelService }, { type: ChatClientService }, { type: TransliterationService }, { type: EmojiInputService }, { type: CustomTemplatesService }, { type: ThemeService }, { type: i0.ChangeDetectorRef }]; }, propDecorators: { class: [{
6316
6482
  type: HostBinding
6317
6483
  }], value: [{
@@ -7384,10 +7550,10 @@ class MessageListComponent {
7384
7550
  }
7385
7551
  }
7386
7552
  MessageListComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.4", ngImport: i0, type: MessageListComponent, deps: [{ token: ChannelService }, { token: ChatClientService }, { token: CustomTemplatesService }, { token: DateParserService }, { token: i0.NgZone }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
7387
- MessageListComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.0.4", type: MessageListComponent, selector: "stream-message-list", inputs: { mode: "mode", direction: "direction", hideJumpToLatestButtonDuringScroll: "hideJumpToLatestButtonDuringScroll", displayDateSeparator: "displayDateSeparator", displayUnreadSeparator: "displayUnreadSeparator", dateSeparatorTextPos: "dateSeparatorTextPos", openMessageListAt: "openMessageListAt", hideUnreadCountForNotificationAndIndicator: "hideUnreadCountForNotificationAndIndicator", displayLoadingIndicator: "displayLoadingIndicator" }, 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: "<ng-container\n *ngIf=\"\n lastReadMessageId &&\n isUnreadNotificationVisible &&\n openMessageListAt === 'last-message' &&\n displayUnreadSeparator\n \"\n>\n <ng-container\n *ngTemplateOutlet=\"\n customnewMessagesNotificationTemplate ||\n defaultUnreadMessagesNotification;\n context: {\n unreadCount: unreadCount,\n onDismiss: messageNotificationDismissClicked,\n onJump: messageNotificationJumpClicked\n }\n \"\n ></ng-container>\n</ng-container>\n<ng-template\n #defaultUnreadMessagesNotification\n let-unreadCount=\"unreadCount\"\n let-onDismiss=\"onDismiss\"\n let-onJump=\"onJump\"\n>\n <div\n class=\"str-chat__unread-messages-notification\"\n data-testid=\"unread-messages-notification\"\n >\n <button\n data-testid=\"unread-messages-notification-jump-to-message\"\n (click)=\"onJump()\"\n >\n <ng-container\n *ngIf=\"\n unreadCount > 0 && !hideUnreadCountForNotificationAndIndicator;\n else noUnreadCount\n \"\n >\n {{\n (unreadCount === 1\n ? \"streamChat.\\{\\{count\\}\\} unread message\"\n : \"streamChat.\\{\\{count\\}\\} unread messages\"\n ) | translate: { count: unreadCount }\n }}\n </ng-container>\n <ng-template #noUnreadCount>\n {{ \"streamChat.Unread messages\" | translate }}\n </ng-template>\n </button>\n <button\n data-testid=\"unread-messages-notification-dismiss\"\n (click)=\"onDismiss()\"\n >\n <stream-icon-placeholder icon=\"close\"></stream-icon-placeholder>\n </button>\n </div>\n</ng-template>\n<div #scrollContainer data-testid=\"scroll-container\" class=\"str-chat__list\">\n <ng-container *ngIf=\"mode === 'main' && isEmpty && emptyListTemplate\">\n <ng-container *ngTemplateOutlet=\"emptyListTemplate\"></ng-container>\n </ng-container>\n <div class=\"str-chat__reverse-infinite-scroll str-chat__message-list-scroll\">\n <ul class=\"str-chat__ul\">\n <li\n *ngIf=\"mode === 'thread' && parentMessage\"\n #parentMessageElement\n data-testid=\"parent-message\"\n class=\"str-chat__parent-message-li\"\n >\n <ng-container\n *ngTemplateOutlet=\"\n messageTemplateContainer;\n context: { message: parentMessage, index: 'parent' }\n \"\n ></ng-container>\n <div data-testid=\"reply-count\" class=\"str-chat__thread-start\">\n {{parentMessage.reply_count === 1 ? ('streamChat.1 reply' | translate) : ('streamChat.{{ replyCount }}\n replies' | translate:replyCountParam)}}\n </div>\n </li>\n <ng-container *ngIf=\"mode === 'thread' && isEmpty && emptyListTemplate\">\n <ng-container *ngTemplateOutlet=\"emptyListTemplate\"></ng-container>\n </ng-container>\n <stream-loading-indicator-placeholder\n *ngIf=\"\n ((loadingState === 'loading-top' && direction === 'bottom-to-top') ||\n (loadingState === 'loading-bottom' &&\n direction === 'top-to-bottom')) &&\n displayLoadingIndicator;\n else loadingIndicatorPlaceholder\n \"\n data-testid=\"top-loading-indicator\"\n ></stream-loading-indicator-placeholder>\n <ng-container *ngIf=\"messages$ | async as messages\">\n <ng-container\n *ngFor=\"\n let message of messages;\n let i = index;\n let isFirst = first;\n let isLast = last;\n trackBy: trackByMessageId\n \"\n >\n <ng-container *ngIf=\"isFirst\">\n <ng-container\n *ngTemplateOutlet=\"\n dateSeparator;\n context: {\n date: message.created_at,\n parsedDate: parseDate(message.created_at)\n }\n \"\n ></ng-container>\n </ng-container>\n <li\n tabindex=\"0\"\n data-testclass=\"message\"\n class=\"str-chat__li str-chat__li--{{ groupStyles[i] }}\"\n id=\"{{ message.id }}\"\n >\n <ng-container\n *ngTemplateOutlet=\"\n messageTemplateContainer;\n context: { message: message, index: i }\n \"\n ></ng-container>\n </li>\n <ng-container\n *ngIf=\"\n (lastReadMessageId === message?.id &&\n direction === 'bottom-to-top') ||\n (direction === 'top-to-bottom' &&\n lastReadMessageId === messages[i + 1]?.id)\n \"\n >\n <li\n *ngIf=\"displayUnreadSeparator\"\n id=\"stream-chat-new-message-indicator\"\n data-testid=\"new-messages-indicator\"\n class=\"str-chat__li str-chat__unread-messages-separator-wrapper\"\n >\n <ng-container\n *ngTemplateOutlet=\"\n customnewMessagesIndicatorTemplate ||\n defaultNewMessagesIndicator;\n context: { unreadCount: unreadCount }\n \"\n ></ng-container>\n </li>\n </ng-container>\n <ng-container *ngIf=\"isNextMessageOnSeparateDate[i]\">\n <ng-container\n *ngTemplateOutlet=\"\n dateSeparator;\n context: {\n date: messages[i + 1].created_at,\n parsedDate: parseDate(messages[i + 1].created_at)\n }\n \"\n ></ng-container>\n </ng-container>\n </ng-container>\n </ng-container>\n <stream-loading-indicator-placeholder\n *ngIf=\"\n ((loadingState === 'loading-bottom' &&\n direction === 'bottom-to-top') ||\n (loadingState === 'loading-top' &&\n direction === 'top-to-bottom')) &&\n displayLoadingIndicator;\n else loadingIndicatorPlaceholder\n \"\n data-testid=\"bottom-loading-indicator\"\n ></stream-loading-indicator-placeholder>\n <ng-template #loadingIndicatorPlaceholder>\n <div class=\"str-chat__loading-indicator-placeholder\"></div>\n </ng-template>\n </ul>\n <ng-template #defaultTypingIndicator let-usersTyping$=\"usersTyping$\">\n <!-- eslint-disable-next-line @angular-eslint/template/no-any -->\n <ng-container *ngIf=\"$any(usersTyping$ | async) as users\">\n <div\n *ngIf=\"users.length > 0\"\n data-testid=\"typing-indicator\"\n class=\"str-chat__typing-indicator str-chat__typing-indicator--typing\"\n >\n <div class=\"str-chat__typing-indicator__dots\">\n <span class=\"str-chat__typing-indicator__dot\"></span>\n <span class=\"str-chat__typing-indicator__dot\"></span>\n <span class=\"str-chat__typing-indicator__dot\"></span>\n </div>\n <div\n data-testid=\"typing-users\"\n class=\"str-chat__typing-indicator__users\"\n >\n {{\n users.length === 1\n ? (\"streamChat.user is typing\"\n | translate: { user: getTypingIndicatorText(users) })\n : (\"streamChat.users are typing\"\n | translate: { users: getTypingIndicatorText(users) })\n }}\n </div>\n </div>\n </ng-container>\n </ng-template>\n <ng-container\n *ngTemplateOutlet=\"\n typingIndicatorTemplate || defaultTypingIndicator;\n context: getTypingIndicatorContext()\n \"\n ></ng-container>\n </div>\n</div>\n<div class=\"str-chat__jump-to-latest-message\">\n <button\n *ngIf=\"isUserScrolled && isJumpToLatestButtonVisible\"\n data-testid=\"scroll-to-latest\"\n class=\"\n str-chat__message-notification-scroll-to-latest\n str-chat__message-notification-scroll-to-latest-right\n str-chat__circle-fab\n \"\n (keyup.enter)=\"jumpToLatestMessage()\"\n (click)=\"jumpToLatestMessage()\"\n >\n <stream-icon\n class=\"str-chat__jump-to-latest-icon str-chat__circle-fab-icon\"\n [icon]=\"direction === 'bottom-to-top' ? 'arrow-down' : 'arrow-up'\"\n ></stream-icon>\n <div\n *ngIf=\"newMessageCountWhileBeingScrolled > 0\"\n class=\"\n str-chat__message-notification\n str-chat__message-notification-scroll-to-latest-unread-count\n str-chat__jump-to-latest-unread-count\n \"\n >\n {{ newMessageCountWhileBeingScrolled }}\n </div>\n </button>\n</div>\n\n<ng-template #messageTemplateContainer let-message=\"message\" let-index=\"index\">\n <ng-template\n #defaultMessageTemplate\n let-messageInput=\"message\"\n let-isLastSentMessage=\"isLastSentMessage\"\n let-enabledMessageActions=\"enabledMessageActions\"\n let-mode=\"mode\"\n let-isHighlighted=\"isHighlighted\"\n let-scroll$=\"scroll$\"\n >\n <stream-message\n [message]=\"messageInput\"\n [isLastSentMessage]=\"isLastSentMessage\"\n [enabledMessageActions]=\"enabledMessageActions\"\n [mode]=\"mode\"\n [isHighlighted]=\"isHighlighted\"\n [scroll$]=\"scroll$\"\n ></stream-message>\n </ng-template>\n <ng-container\n *ngTemplateOutlet=\"\n messageTemplate || defaultMessageTemplate;\n context: {\n message: message,\n isLastSentMessage: !!(\n lastSentMessageId && message?.id === lastSentMessageId\n ),\n enabledMessageActions: enabledMessageActions,\n mode: mode,\n isHighlighted: message?.id === highlightedMessageId,\n scroll$: scroll$\n }\n \"\n ></ng-container>\n</ng-template>\n\n<ng-template #dateSeparator let-date=\"date\" let-parsedDate=\"parsedDate\">\n <ng-container *ngIf=\"displayDateSeparator\">\n <ng-container\n *ngTemplateOutlet=\"\n customDateSeparatorTemplate || defaultDateSeparator;\n context: {\n date: date,\n parsedDate: parsedDate\n }\n \"\n ></ng-container>\n </ng-container>\n\n <ng-template\n #defaultDateSeparator\n let-date=\"date\"\n let-parsedDate=\"parsedDate\"\n >\n <div data-testid=\"date-separator\" class=\"str-chat__date-separator\">\n <hr\n *ngIf=\"\n dateSeparatorTextPos === 'right' || dateSeparatorTextPos === 'center'\n \"\n class=\"str-chat__date-separator-line\"\n />\n <div class=\"str-chat__date-separator-date\">\n {{ parsedDate }}\n </div>\n <hr\n *ngIf=\"\n dateSeparatorTextPos === 'left' || dateSeparatorTextPos === 'center'\n \"\n class=\"str-chat__date-separator-line\"\n />\n </div>\n </ng-template>\n</ng-template>\n\n<ng-template #defaultNewMessagesIndicator let-unreadCount=\"unreadCount\">\n <div class=\"str-chat__unread-messages-separator\">\n <ng-container\n *ngIf=\"\n unreadCount > 0 && !hideUnreadCountForNotificationAndIndicator;\n else noUnreadCount\n \"\n >\n {{\n (unreadCount === 1\n ? \"streamChat.\\{\\{count\\}\\} unread message\"\n : \"streamChat.\\{\\{count\\}\\} unread messages\"\n ) | translate: { count: unreadCount }\n }}\n </ng-container>\n <ng-template #noUnreadCount>\n {{ \"streamChat.Unread messages\" | translate }}\n </ng-template>\n </div>\n</ng-template>\n", dependencies: [{ kind: "directive", type: i4.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i4.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: MessageComponent, selector: "stream-message", inputs: ["message", "enabledMessageActions", "isLastSentMessage", "mode", "isHighlighted", "scroll$"] }, { kind: "component", type: IconComponent, selector: "stream-icon", inputs: ["icon"] }, { kind: "component", type: IconPlaceholderComponent, selector: "stream-icon-placeholder", inputs: ["icon"] }, { kind: "component", type: LoadingIndicatorPlaceholderComponent, selector: "stream-loading-indicator-placeholder" }, { kind: "pipe", type: i4.AsyncPipe, name: "async" }, { kind: "pipe", type: i10.TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
7553
+ MessageListComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.0.4", type: MessageListComponent, selector: "stream-message-list", inputs: { mode: "mode", direction: "direction", hideJumpToLatestButtonDuringScroll: "hideJumpToLatestButtonDuringScroll", displayDateSeparator: "displayDateSeparator", displayUnreadSeparator: "displayUnreadSeparator", dateSeparatorTextPos: "dateSeparatorTextPos", openMessageListAt: "openMessageListAt", hideUnreadCountForNotificationAndIndicator: "hideUnreadCountForNotificationAndIndicator", displayLoadingIndicator: "displayLoadingIndicator" }, 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: "<ng-container\n *ngIf=\"\n lastReadMessageId &&\n isUnreadNotificationVisible &&\n openMessageListAt === 'last-message' &&\n displayUnreadSeparator\n \"\n>\n <ng-container\n *ngTemplateOutlet=\"\n customnewMessagesNotificationTemplate ||\n defaultUnreadMessagesNotification;\n context: {\n unreadCount: unreadCount,\n onDismiss: messageNotificationDismissClicked,\n onJump: messageNotificationJumpClicked\n }\n \"\n ></ng-container>\n</ng-container>\n<ng-template\n #defaultUnreadMessagesNotification\n let-unreadCount=\"unreadCount\"\n let-onDismiss=\"onDismiss\"\n let-onJump=\"onJump\"\n>\n <div\n class=\"str-chat__unread-messages-notification\"\n data-testid=\"unread-messages-notification\"\n >\n <button\n data-testid=\"unread-messages-notification-jump-to-message\"\n (click)=\"onJump()\"\n >\n <ng-container\n *ngIf=\"\n unreadCount > 0 && !hideUnreadCountForNotificationAndIndicator;\n else noUnreadCount\n \"\n >\n {{\n (unreadCount === 1\n ? \"streamChat.\\{\\{count\\}\\} unread message\"\n : \"streamChat.\\{\\{count\\}\\} unread messages\"\n ) | translate : { count: unreadCount }\n }}\n </ng-container>\n <ng-template #noUnreadCount>\n {{ \"streamChat.Unread messages\" | translate }}\n </ng-template>\n </button>\n <button\n data-testid=\"unread-messages-notification-dismiss\"\n (click)=\"onDismiss()\"\n >\n <stream-icon-placeholder icon=\"close\"></stream-icon-placeholder>\n </button>\n </div>\n</ng-template>\n<div #scrollContainer data-testid=\"scroll-container\" class=\"str-chat__list\">\n <ng-container *ngIf=\"mode === 'main' && isEmpty && emptyListTemplate\">\n <ng-container *ngTemplateOutlet=\"emptyListTemplate\"></ng-container>\n </ng-container>\n <div class=\"str-chat__reverse-infinite-scroll str-chat__message-list-scroll\">\n <ul class=\"str-chat__ul\">\n <li\n *ngIf=\"mode === 'thread' && parentMessage\"\n #parentMessageElement\n data-testid=\"parent-message\"\n class=\"str-chat__parent-message-li\"\n >\n <ng-container\n *ngTemplateOutlet=\"\n messageTemplateContainer;\n context: { message: parentMessage, index: 'parent' }\n \"\n ></ng-container>\n <div data-testid=\"reply-count\" class=\"str-chat__thread-start\">\n {{parentMessage.reply_count === 1 ? ('streamChat.1 reply' | translate) : ('streamChat.{{ replyCount }}\n replies' | translate:replyCountParam)}}\n </div>\n </li>\n <ng-container *ngIf=\"mode === 'thread' && isEmpty && emptyListTemplate\">\n <ng-container *ngTemplateOutlet=\"emptyListTemplate\"></ng-container>\n </ng-container>\n <stream-loading-indicator-placeholder\n *ngIf=\"\n ((loadingState === 'loading-top' && direction === 'bottom-to-top') ||\n (loadingState === 'loading-bottom' &&\n direction === 'top-to-bottom')) &&\n displayLoadingIndicator;\n else loadingIndicatorPlaceholder\n \"\n data-testid=\"top-loading-indicator\"\n ></stream-loading-indicator-placeholder>\n <ng-container *ngIf=\"messages$ | async as messages\">\n <ng-container\n *ngFor=\"\n let message of messages;\n let i = index;\n let isFirst = first;\n let isLast = last;\n trackBy: trackByMessageId\n \"\n >\n <ng-container *ngIf=\"isFirst\">\n <ng-container\n *ngTemplateOutlet=\"\n dateSeparator;\n context: {\n date: message.created_at,\n parsedDate: parseDate(message.created_at)\n }\n \"\n ></ng-container>\n </ng-container>\n <li\n tabindex=\"0\"\n data-testclass=\"message\"\n class=\"str-chat__li str-chat__li--{{ groupStyles[i] }}\"\n id=\"{{ message.id }}\"\n >\n <ng-container\n *ngTemplateOutlet=\"\n messageTemplateContainer;\n context: { message: message, index: i }\n \"\n ></ng-container>\n </li>\n <ng-container\n *ngIf=\"\n (lastReadMessageId === message?.id &&\n direction === 'bottom-to-top') ||\n (direction === 'top-to-bottom' &&\n lastReadMessageId === messages[i + 1]?.id)\n \"\n >\n <li\n *ngIf=\"displayUnreadSeparator\"\n id=\"stream-chat-new-message-indicator\"\n data-testid=\"new-messages-indicator\"\n class=\"str-chat__li str-chat__unread-messages-separator-wrapper\"\n >\n <ng-container\n *ngTemplateOutlet=\"\n customnewMessagesIndicatorTemplate ||\n defaultNewMessagesIndicator;\n context: { unreadCount: unreadCount }\n \"\n ></ng-container>\n </li>\n </ng-container>\n <ng-container *ngIf=\"isNextMessageOnSeparateDate[i]\">\n <ng-container\n *ngTemplateOutlet=\"\n dateSeparator;\n context: {\n date: messages[i + 1].created_at,\n parsedDate: parseDate(messages[i + 1].created_at)\n }\n \"\n ></ng-container>\n </ng-container>\n </ng-container>\n </ng-container>\n <stream-loading-indicator-placeholder\n *ngIf=\"\n ((loadingState === 'loading-bottom' &&\n direction === 'bottom-to-top') ||\n (loadingState === 'loading-top' &&\n direction === 'top-to-bottom')) &&\n displayLoadingIndicator;\n else loadingIndicatorPlaceholder\n \"\n data-testid=\"bottom-loading-indicator\"\n ></stream-loading-indicator-placeholder>\n <ng-template #loadingIndicatorPlaceholder>\n <div class=\"str-chat__loading-indicator-placeholder\"></div>\n </ng-template>\n </ul>\n <ng-template #defaultTypingIndicator let-usersTyping$=\"usersTyping$\">\n <!-- eslint-disable-next-line @angular-eslint/template/no-any -->\n <ng-container *ngIf=\"$any(usersTyping$ | async) as users\">\n <div\n *ngIf=\"users.length > 0\"\n data-testid=\"typing-indicator\"\n class=\"str-chat__typing-indicator str-chat__typing-indicator--typing\"\n >\n <div class=\"str-chat__typing-indicator__dots\">\n <span class=\"str-chat__typing-indicator__dot\"></span>\n <span class=\"str-chat__typing-indicator__dot\"></span>\n <span class=\"str-chat__typing-indicator__dot\"></span>\n </div>\n <div\n data-testid=\"typing-users\"\n class=\"str-chat__typing-indicator__users\"\n >\n {{\n users.length === 1\n ? (\"streamChat.user is typing\"\n | translate : { user: getTypingIndicatorText(users) })\n : (\"streamChat.users are typing\"\n | translate : { users: getTypingIndicatorText(users) })\n }}\n </div>\n </div>\n </ng-container>\n </ng-template>\n <ng-container\n *ngTemplateOutlet=\"\n typingIndicatorTemplate || defaultTypingIndicator;\n context: getTypingIndicatorContext()\n \"\n ></ng-container>\n </div>\n</div>\n<div class=\"str-chat__jump-to-latest-message\">\n <button\n *ngIf=\"isUserScrolled && isJumpToLatestButtonVisible\"\n data-testid=\"scroll-to-latest\"\n class=\"str-chat__message-notification-scroll-to-latest str-chat__message-notification-scroll-to-latest-right str-chat__circle-fab\"\n (keyup.enter)=\"jumpToLatestMessage()\"\n (click)=\"jumpToLatestMessage()\"\n >\n <stream-icon\n class=\"str-chat__jump-to-latest-icon str-chat__circle-fab-icon\"\n [icon]=\"direction === 'bottom-to-top' ? 'arrow-down' : 'arrow-up'\"\n ></stream-icon>\n <div\n *ngIf=\"newMessageCountWhileBeingScrolled > 0\"\n class=\"str-chat__message-notification str-chat__message-notification-scroll-to-latest-unread-count str-chat__jump-to-latest-unread-count\"\n >\n {{ newMessageCountWhileBeingScrolled }}\n </div>\n </button>\n</div>\n\n<ng-template #messageTemplateContainer let-message=\"message\" let-index=\"index\">\n <ng-template\n #defaultMessageTemplate\n let-messageInput=\"message\"\n let-isLastSentMessage=\"isLastSentMessage\"\n let-enabledMessageActions=\"enabledMessageActions\"\n let-mode=\"mode\"\n let-isHighlighted=\"isHighlighted\"\n let-scroll$=\"scroll$\"\n >\n <stream-message\n [message]=\"messageInput\"\n [isLastSentMessage]=\"isLastSentMessage\"\n [enabledMessageActions]=\"enabledMessageActions\"\n [mode]=\"mode\"\n [isHighlighted]=\"isHighlighted\"\n [scroll$]=\"scroll$\"\n ></stream-message>\n </ng-template>\n <ng-container\n *ngTemplateOutlet=\"\n messageTemplate || defaultMessageTemplate;\n context: {\n message: message,\n isLastSentMessage: !!(\n lastSentMessageId && message?.id === lastSentMessageId\n ),\n enabledMessageActions: enabledMessageActions,\n mode: mode,\n isHighlighted: message?.id === highlightedMessageId,\n scroll$: scroll$\n }\n \"\n ></ng-container>\n</ng-template>\n\n<ng-template #dateSeparator let-date=\"date\" let-parsedDate=\"parsedDate\">\n <ng-container *ngIf=\"displayDateSeparator\">\n <ng-container\n *ngTemplateOutlet=\"\n customDateSeparatorTemplate || defaultDateSeparator;\n context: {\n date: date,\n parsedDate: parsedDate\n }\n \"\n ></ng-container>\n </ng-container>\n\n <ng-template\n #defaultDateSeparator\n let-date=\"date\"\n let-parsedDate=\"parsedDate\"\n >\n <div data-testid=\"date-separator\" class=\"str-chat__date-separator\">\n <hr\n *ngIf=\"\n dateSeparatorTextPos === 'right' || dateSeparatorTextPos === 'center'\n \"\n class=\"str-chat__date-separator-line\"\n />\n <div class=\"str-chat__date-separator-date\">\n {{ parsedDate }}\n </div>\n <hr\n *ngIf=\"\n dateSeparatorTextPos === 'left' || dateSeparatorTextPos === 'center'\n \"\n class=\"str-chat__date-separator-line\"\n />\n </div>\n </ng-template>\n</ng-template>\n\n<ng-template #defaultNewMessagesIndicator let-unreadCount=\"unreadCount\">\n <div class=\"str-chat__unread-messages-separator\">\n <ng-container\n *ngIf=\"\n unreadCount > 0 && !hideUnreadCountForNotificationAndIndicator;\n else noUnreadCount\n \"\n >\n {{\n (unreadCount === 1\n ? \"streamChat.\\{\\{count\\}\\} unread message\"\n : \"streamChat.\\{\\{count\\}\\} unread messages\"\n ) | translate : { count: unreadCount }\n }}\n </ng-container>\n <ng-template #noUnreadCount>\n {{ \"streamChat.Unread messages\" | translate }}\n </ng-template>\n </div>\n</ng-template>\n", dependencies: [{ kind: "directive", type: i4.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i4.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: MessageComponent, selector: "stream-message", inputs: ["message", "enabledMessageActions", "isLastSentMessage", "mode", "isHighlighted", "scroll$"] }, { kind: "component", type: IconComponent, selector: "stream-icon", inputs: ["icon"] }, { kind: "component", type: IconPlaceholderComponent, selector: "stream-icon-placeholder", inputs: ["icon"] }, { kind: "component", type: LoadingIndicatorPlaceholderComponent, selector: "stream-loading-indicator-placeholder" }, { kind: "pipe", type: i4.AsyncPipe, name: "async" }, { kind: "pipe", type: i10.TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
7388
7554
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.4", ngImport: i0, type: MessageListComponent, decorators: [{
7389
7555
  type: Component,
7390
- args: [{ selector: 'stream-message-list', changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-container\n *ngIf=\"\n lastReadMessageId &&\n isUnreadNotificationVisible &&\n openMessageListAt === 'last-message' &&\n displayUnreadSeparator\n \"\n>\n <ng-container\n *ngTemplateOutlet=\"\n customnewMessagesNotificationTemplate ||\n defaultUnreadMessagesNotification;\n context: {\n unreadCount: unreadCount,\n onDismiss: messageNotificationDismissClicked,\n onJump: messageNotificationJumpClicked\n }\n \"\n ></ng-container>\n</ng-container>\n<ng-template\n #defaultUnreadMessagesNotification\n let-unreadCount=\"unreadCount\"\n let-onDismiss=\"onDismiss\"\n let-onJump=\"onJump\"\n>\n <div\n class=\"str-chat__unread-messages-notification\"\n data-testid=\"unread-messages-notification\"\n >\n <button\n data-testid=\"unread-messages-notification-jump-to-message\"\n (click)=\"onJump()\"\n >\n <ng-container\n *ngIf=\"\n unreadCount > 0 && !hideUnreadCountForNotificationAndIndicator;\n else noUnreadCount\n \"\n >\n {{\n (unreadCount === 1\n ? \"streamChat.\\{\\{count\\}\\} unread message\"\n : \"streamChat.\\{\\{count\\}\\} unread messages\"\n ) | translate: { count: unreadCount }\n }}\n </ng-container>\n <ng-template #noUnreadCount>\n {{ \"streamChat.Unread messages\" | translate }}\n </ng-template>\n </button>\n <button\n data-testid=\"unread-messages-notification-dismiss\"\n (click)=\"onDismiss()\"\n >\n <stream-icon-placeholder icon=\"close\"></stream-icon-placeholder>\n </button>\n </div>\n</ng-template>\n<div #scrollContainer data-testid=\"scroll-container\" class=\"str-chat__list\">\n <ng-container *ngIf=\"mode === 'main' && isEmpty && emptyListTemplate\">\n <ng-container *ngTemplateOutlet=\"emptyListTemplate\"></ng-container>\n </ng-container>\n <div class=\"str-chat__reverse-infinite-scroll str-chat__message-list-scroll\">\n <ul class=\"str-chat__ul\">\n <li\n *ngIf=\"mode === 'thread' && parentMessage\"\n #parentMessageElement\n data-testid=\"parent-message\"\n class=\"str-chat__parent-message-li\"\n >\n <ng-container\n *ngTemplateOutlet=\"\n messageTemplateContainer;\n context: { message: parentMessage, index: 'parent' }\n \"\n ></ng-container>\n <div data-testid=\"reply-count\" class=\"str-chat__thread-start\">\n {{parentMessage.reply_count === 1 ? ('streamChat.1 reply' | translate) : ('streamChat.{{ replyCount }}\n replies' | translate:replyCountParam)}}\n </div>\n </li>\n <ng-container *ngIf=\"mode === 'thread' && isEmpty && emptyListTemplate\">\n <ng-container *ngTemplateOutlet=\"emptyListTemplate\"></ng-container>\n </ng-container>\n <stream-loading-indicator-placeholder\n *ngIf=\"\n ((loadingState === 'loading-top' && direction === 'bottom-to-top') ||\n (loadingState === 'loading-bottom' &&\n direction === 'top-to-bottom')) &&\n displayLoadingIndicator;\n else loadingIndicatorPlaceholder\n \"\n data-testid=\"top-loading-indicator\"\n ></stream-loading-indicator-placeholder>\n <ng-container *ngIf=\"messages$ | async as messages\">\n <ng-container\n *ngFor=\"\n let message of messages;\n let i = index;\n let isFirst = first;\n let isLast = last;\n trackBy: trackByMessageId\n \"\n >\n <ng-container *ngIf=\"isFirst\">\n <ng-container\n *ngTemplateOutlet=\"\n dateSeparator;\n context: {\n date: message.created_at,\n parsedDate: parseDate(message.created_at)\n }\n \"\n ></ng-container>\n </ng-container>\n <li\n tabindex=\"0\"\n data-testclass=\"message\"\n class=\"str-chat__li str-chat__li--{{ groupStyles[i] }}\"\n id=\"{{ message.id }}\"\n >\n <ng-container\n *ngTemplateOutlet=\"\n messageTemplateContainer;\n context: { message: message, index: i }\n \"\n ></ng-container>\n </li>\n <ng-container\n *ngIf=\"\n (lastReadMessageId === message?.id &&\n direction === 'bottom-to-top') ||\n (direction === 'top-to-bottom' &&\n lastReadMessageId === messages[i + 1]?.id)\n \"\n >\n <li\n *ngIf=\"displayUnreadSeparator\"\n id=\"stream-chat-new-message-indicator\"\n data-testid=\"new-messages-indicator\"\n class=\"str-chat__li str-chat__unread-messages-separator-wrapper\"\n >\n <ng-container\n *ngTemplateOutlet=\"\n customnewMessagesIndicatorTemplate ||\n defaultNewMessagesIndicator;\n context: { unreadCount: unreadCount }\n \"\n ></ng-container>\n </li>\n </ng-container>\n <ng-container *ngIf=\"isNextMessageOnSeparateDate[i]\">\n <ng-container\n *ngTemplateOutlet=\"\n dateSeparator;\n context: {\n date: messages[i + 1].created_at,\n parsedDate: parseDate(messages[i + 1].created_at)\n }\n \"\n ></ng-container>\n </ng-container>\n </ng-container>\n </ng-container>\n <stream-loading-indicator-placeholder\n *ngIf=\"\n ((loadingState === 'loading-bottom' &&\n direction === 'bottom-to-top') ||\n (loadingState === 'loading-top' &&\n direction === 'top-to-bottom')) &&\n displayLoadingIndicator;\n else loadingIndicatorPlaceholder\n \"\n data-testid=\"bottom-loading-indicator\"\n ></stream-loading-indicator-placeholder>\n <ng-template #loadingIndicatorPlaceholder>\n <div class=\"str-chat__loading-indicator-placeholder\"></div>\n </ng-template>\n </ul>\n <ng-template #defaultTypingIndicator let-usersTyping$=\"usersTyping$\">\n <!-- eslint-disable-next-line @angular-eslint/template/no-any -->\n <ng-container *ngIf=\"$any(usersTyping$ | async) as users\">\n <div\n *ngIf=\"users.length > 0\"\n data-testid=\"typing-indicator\"\n class=\"str-chat__typing-indicator str-chat__typing-indicator--typing\"\n >\n <div class=\"str-chat__typing-indicator__dots\">\n <span class=\"str-chat__typing-indicator__dot\"></span>\n <span class=\"str-chat__typing-indicator__dot\"></span>\n <span class=\"str-chat__typing-indicator__dot\"></span>\n </div>\n <div\n data-testid=\"typing-users\"\n class=\"str-chat__typing-indicator__users\"\n >\n {{\n users.length === 1\n ? (\"streamChat.user is typing\"\n | translate: { user: getTypingIndicatorText(users) })\n : (\"streamChat.users are typing\"\n | translate: { users: getTypingIndicatorText(users) })\n }}\n </div>\n </div>\n </ng-container>\n </ng-template>\n <ng-container\n *ngTemplateOutlet=\"\n typingIndicatorTemplate || defaultTypingIndicator;\n context: getTypingIndicatorContext()\n \"\n ></ng-container>\n </div>\n</div>\n<div class=\"str-chat__jump-to-latest-message\">\n <button\n *ngIf=\"isUserScrolled && isJumpToLatestButtonVisible\"\n data-testid=\"scroll-to-latest\"\n class=\"\n str-chat__message-notification-scroll-to-latest\n str-chat__message-notification-scroll-to-latest-right\n str-chat__circle-fab\n \"\n (keyup.enter)=\"jumpToLatestMessage()\"\n (click)=\"jumpToLatestMessage()\"\n >\n <stream-icon\n class=\"str-chat__jump-to-latest-icon str-chat__circle-fab-icon\"\n [icon]=\"direction === 'bottom-to-top' ? 'arrow-down' : 'arrow-up'\"\n ></stream-icon>\n <div\n *ngIf=\"newMessageCountWhileBeingScrolled > 0\"\n class=\"\n str-chat__message-notification\n str-chat__message-notification-scroll-to-latest-unread-count\n str-chat__jump-to-latest-unread-count\n \"\n >\n {{ newMessageCountWhileBeingScrolled }}\n </div>\n </button>\n</div>\n\n<ng-template #messageTemplateContainer let-message=\"message\" let-index=\"index\">\n <ng-template\n #defaultMessageTemplate\n let-messageInput=\"message\"\n let-isLastSentMessage=\"isLastSentMessage\"\n let-enabledMessageActions=\"enabledMessageActions\"\n let-mode=\"mode\"\n let-isHighlighted=\"isHighlighted\"\n let-scroll$=\"scroll$\"\n >\n <stream-message\n [message]=\"messageInput\"\n [isLastSentMessage]=\"isLastSentMessage\"\n [enabledMessageActions]=\"enabledMessageActions\"\n [mode]=\"mode\"\n [isHighlighted]=\"isHighlighted\"\n [scroll$]=\"scroll$\"\n ></stream-message>\n </ng-template>\n <ng-container\n *ngTemplateOutlet=\"\n messageTemplate || defaultMessageTemplate;\n context: {\n message: message,\n isLastSentMessage: !!(\n lastSentMessageId && message?.id === lastSentMessageId\n ),\n enabledMessageActions: enabledMessageActions,\n mode: mode,\n isHighlighted: message?.id === highlightedMessageId,\n scroll$: scroll$\n }\n \"\n ></ng-container>\n</ng-template>\n\n<ng-template #dateSeparator let-date=\"date\" let-parsedDate=\"parsedDate\">\n <ng-container *ngIf=\"displayDateSeparator\">\n <ng-container\n *ngTemplateOutlet=\"\n customDateSeparatorTemplate || defaultDateSeparator;\n context: {\n date: date,\n parsedDate: parsedDate\n }\n \"\n ></ng-container>\n </ng-container>\n\n <ng-template\n #defaultDateSeparator\n let-date=\"date\"\n let-parsedDate=\"parsedDate\"\n >\n <div data-testid=\"date-separator\" class=\"str-chat__date-separator\">\n <hr\n *ngIf=\"\n dateSeparatorTextPos === 'right' || dateSeparatorTextPos === 'center'\n \"\n class=\"str-chat__date-separator-line\"\n />\n <div class=\"str-chat__date-separator-date\">\n {{ parsedDate }}\n </div>\n <hr\n *ngIf=\"\n dateSeparatorTextPos === 'left' || dateSeparatorTextPos === 'center'\n \"\n class=\"str-chat__date-separator-line\"\n />\n </div>\n </ng-template>\n</ng-template>\n\n<ng-template #defaultNewMessagesIndicator let-unreadCount=\"unreadCount\">\n <div class=\"str-chat__unread-messages-separator\">\n <ng-container\n *ngIf=\"\n unreadCount > 0 && !hideUnreadCountForNotificationAndIndicator;\n else noUnreadCount\n \"\n >\n {{\n (unreadCount === 1\n ? \"streamChat.\\{\\{count\\}\\} unread message\"\n : \"streamChat.\\{\\{count\\}\\} unread messages\"\n ) | translate: { count: unreadCount }\n }}\n </ng-container>\n <ng-template #noUnreadCount>\n {{ \"streamChat.Unread messages\" | translate }}\n </ng-template>\n </div>\n</ng-template>\n" }]
7556
+ args: [{ selector: 'stream-message-list', changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-container\n *ngIf=\"\n lastReadMessageId &&\n isUnreadNotificationVisible &&\n openMessageListAt === 'last-message' &&\n displayUnreadSeparator\n \"\n>\n <ng-container\n *ngTemplateOutlet=\"\n customnewMessagesNotificationTemplate ||\n defaultUnreadMessagesNotification;\n context: {\n unreadCount: unreadCount,\n onDismiss: messageNotificationDismissClicked,\n onJump: messageNotificationJumpClicked\n }\n \"\n ></ng-container>\n</ng-container>\n<ng-template\n #defaultUnreadMessagesNotification\n let-unreadCount=\"unreadCount\"\n let-onDismiss=\"onDismiss\"\n let-onJump=\"onJump\"\n>\n <div\n class=\"str-chat__unread-messages-notification\"\n data-testid=\"unread-messages-notification\"\n >\n <button\n data-testid=\"unread-messages-notification-jump-to-message\"\n (click)=\"onJump()\"\n >\n <ng-container\n *ngIf=\"\n unreadCount > 0 && !hideUnreadCountForNotificationAndIndicator;\n else noUnreadCount\n \"\n >\n {{\n (unreadCount === 1\n ? \"streamChat.\\{\\{count\\}\\} unread message\"\n : \"streamChat.\\{\\{count\\}\\} unread messages\"\n ) | translate : { count: unreadCount }\n }}\n </ng-container>\n <ng-template #noUnreadCount>\n {{ \"streamChat.Unread messages\" | translate }}\n </ng-template>\n </button>\n <button\n data-testid=\"unread-messages-notification-dismiss\"\n (click)=\"onDismiss()\"\n >\n <stream-icon-placeholder icon=\"close\"></stream-icon-placeholder>\n </button>\n </div>\n</ng-template>\n<div #scrollContainer data-testid=\"scroll-container\" class=\"str-chat__list\">\n <ng-container *ngIf=\"mode === 'main' && isEmpty && emptyListTemplate\">\n <ng-container *ngTemplateOutlet=\"emptyListTemplate\"></ng-container>\n </ng-container>\n <div class=\"str-chat__reverse-infinite-scroll str-chat__message-list-scroll\">\n <ul class=\"str-chat__ul\">\n <li\n *ngIf=\"mode === 'thread' && parentMessage\"\n #parentMessageElement\n data-testid=\"parent-message\"\n class=\"str-chat__parent-message-li\"\n >\n <ng-container\n *ngTemplateOutlet=\"\n messageTemplateContainer;\n context: { message: parentMessage, index: 'parent' }\n \"\n ></ng-container>\n <div data-testid=\"reply-count\" class=\"str-chat__thread-start\">\n {{parentMessage.reply_count === 1 ? ('streamChat.1 reply' | translate) : ('streamChat.{{ replyCount }}\n replies' | translate:replyCountParam)}}\n </div>\n </li>\n <ng-container *ngIf=\"mode === 'thread' && isEmpty && emptyListTemplate\">\n <ng-container *ngTemplateOutlet=\"emptyListTemplate\"></ng-container>\n </ng-container>\n <stream-loading-indicator-placeholder\n *ngIf=\"\n ((loadingState === 'loading-top' && direction === 'bottom-to-top') ||\n (loadingState === 'loading-bottom' &&\n direction === 'top-to-bottom')) &&\n displayLoadingIndicator;\n else loadingIndicatorPlaceholder\n \"\n data-testid=\"top-loading-indicator\"\n ></stream-loading-indicator-placeholder>\n <ng-container *ngIf=\"messages$ | async as messages\">\n <ng-container\n *ngFor=\"\n let message of messages;\n let i = index;\n let isFirst = first;\n let isLast = last;\n trackBy: trackByMessageId\n \"\n >\n <ng-container *ngIf=\"isFirst\">\n <ng-container\n *ngTemplateOutlet=\"\n dateSeparator;\n context: {\n date: message.created_at,\n parsedDate: parseDate(message.created_at)\n }\n \"\n ></ng-container>\n </ng-container>\n <li\n tabindex=\"0\"\n data-testclass=\"message\"\n class=\"str-chat__li str-chat__li--{{ groupStyles[i] }}\"\n id=\"{{ message.id }}\"\n >\n <ng-container\n *ngTemplateOutlet=\"\n messageTemplateContainer;\n context: { message: message, index: i }\n \"\n ></ng-container>\n </li>\n <ng-container\n *ngIf=\"\n (lastReadMessageId === message?.id &&\n direction === 'bottom-to-top') ||\n (direction === 'top-to-bottom' &&\n lastReadMessageId === messages[i + 1]?.id)\n \"\n >\n <li\n *ngIf=\"displayUnreadSeparator\"\n id=\"stream-chat-new-message-indicator\"\n data-testid=\"new-messages-indicator\"\n class=\"str-chat__li str-chat__unread-messages-separator-wrapper\"\n >\n <ng-container\n *ngTemplateOutlet=\"\n customnewMessagesIndicatorTemplate ||\n defaultNewMessagesIndicator;\n context: { unreadCount: unreadCount }\n \"\n ></ng-container>\n </li>\n </ng-container>\n <ng-container *ngIf=\"isNextMessageOnSeparateDate[i]\">\n <ng-container\n *ngTemplateOutlet=\"\n dateSeparator;\n context: {\n date: messages[i + 1].created_at,\n parsedDate: parseDate(messages[i + 1].created_at)\n }\n \"\n ></ng-container>\n </ng-container>\n </ng-container>\n </ng-container>\n <stream-loading-indicator-placeholder\n *ngIf=\"\n ((loadingState === 'loading-bottom' &&\n direction === 'bottom-to-top') ||\n (loadingState === 'loading-top' &&\n direction === 'top-to-bottom')) &&\n displayLoadingIndicator;\n else loadingIndicatorPlaceholder\n \"\n data-testid=\"bottom-loading-indicator\"\n ></stream-loading-indicator-placeholder>\n <ng-template #loadingIndicatorPlaceholder>\n <div class=\"str-chat__loading-indicator-placeholder\"></div>\n </ng-template>\n </ul>\n <ng-template #defaultTypingIndicator let-usersTyping$=\"usersTyping$\">\n <!-- eslint-disable-next-line @angular-eslint/template/no-any -->\n <ng-container *ngIf=\"$any(usersTyping$ | async) as users\">\n <div\n *ngIf=\"users.length > 0\"\n data-testid=\"typing-indicator\"\n class=\"str-chat__typing-indicator str-chat__typing-indicator--typing\"\n >\n <div class=\"str-chat__typing-indicator__dots\">\n <span class=\"str-chat__typing-indicator__dot\"></span>\n <span class=\"str-chat__typing-indicator__dot\"></span>\n <span class=\"str-chat__typing-indicator__dot\"></span>\n </div>\n <div\n data-testid=\"typing-users\"\n class=\"str-chat__typing-indicator__users\"\n >\n {{\n users.length === 1\n ? (\"streamChat.user is typing\"\n | translate : { user: getTypingIndicatorText(users) })\n : (\"streamChat.users are typing\"\n | translate : { users: getTypingIndicatorText(users) })\n }}\n </div>\n </div>\n </ng-container>\n </ng-template>\n <ng-container\n *ngTemplateOutlet=\"\n typingIndicatorTemplate || defaultTypingIndicator;\n context: getTypingIndicatorContext()\n \"\n ></ng-container>\n </div>\n</div>\n<div class=\"str-chat__jump-to-latest-message\">\n <button\n *ngIf=\"isUserScrolled && isJumpToLatestButtonVisible\"\n data-testid=\"scroll-to-latest\"\n class=\"str-chat__message-notification-scroll-to-latest str-chat__message-notification-scroll-to-latest-right str-chat__circle-fab\"\n (keyup.enter)=\"jumpToLatestMessage()\"\n (click)=\"jumpToLatestMessage()\"\n >\n <stream-icon\n class=\"str-chat__jump-to-latest-icon str-chat__circle-fab-icon\"\n [icon]=\"direction === 'bottom-to-top' ? 'arrow-down' : 'arrow-up'\"\n ></stream-icon>\n <div\n *ngIf=\"newMessageCountWhileBeingScrolled > 0\"\n class=\"str-chat__message-notification str-chat__message-notification-scroll-to-latest-unread-count str-chat__jump-to-latest-unread-count\"\n >\n {{ newMessageCountWhileBeingScrolled }}\n </div>\n </button>\n</div>\n\n<ng-template #messageTemplateContainer let-message=\"message\" let-index=\"index\">\n <ng-template\n #defaultMessageTemplate\n let-messageInput=\"message\"\n let-isLastSentMessage=\"isLastSentMessage\"\n let-enabledMessageActions=\"enabledMessageActions\"\n let-mode=\"mode\"\n let-isHighlighted=\"isHighlighted\"\n let-scroll$=\"scroll$\"\n >\n <stream-message\n [message]=\"messageInput\"\n [isLastSentMessage]=\"isLastSentMessage\"\n [enabledMessageActions]=\"enabledMessageActions\"\n [mode]=\"mode\"\n [isHighlighted]=\"isHighlighted\"\n [scroll$]=\"scroll$\"\n ></stream-message>\n </ng-template>\n <ng-container\n *ngTemplateOutlet=\"\n messageTemplate || defaultMessageTemplate;\n context: {\n message: message,\n isLastSentMessage: !!(\n lastSentMessageId && message?.id === lastSentMessageId\n ),\n enabledMessageActions: enabledMessageActions,\n mode: mode,\n isHighlighted: message?.id === highlightedMessageId,\n scroll$: scroll$\n }\n \"\n ></ng-container>\n</ng-template>\n\n<ng-template #dateSeparator let-date=\"date\" let-parsedDate=\"parsedDate\">\n <ng-container *ngIf=\"displayDateSeparator\">\n <ng-container\n *ngTemplateOutlet=\"\n customDateSeparatorTemplate || defaultDateSeparator;\n context: {\n date: date,\n parsedDate: parsedDate\n }\n \"\n ></ng-container>\n </ng-container>\n\n <ng-template\n #defaultDateSeparator\n let-date=\"date\"\n let-parsedDate=\"parsedDate\"\n >\n <div data-testid=\"date-separator\" class=\"str-chat__date-separator\">\n <hr\n *ngIf=\"\n dateSeparatorTextPos === 'right' || dateSeparatorTextPos === 'center'\n \"\n class=\"str-chat__date-separator-line\"\n />\n <div class=\"str-chat__date-separator-date\">\n {{ parsedDate }}\n </div>\n <hr\n *ngIf=\"\n dateSeparatorTextPos === 'left' || dateSeparatorTextPos === 'center'\n \"\n class=\"str-chat__date-separator-line\"\n />\n </div>\n </ng-template>\n</ng-template>\n\n<ng-template #defaultNewMessagesIndicator let-unreadCount=\"unreadCount\">\n <div class=\"str-chat__unread-messages-separator\">\n <ng-container\n *ngIf=\"\n unreadCount > 0 && !hideUnreadCountForNotificationAndIndicator;\n else noUnreadCount\n \"\n >\n {{\n (unreadCount === 1\n ? \"streamChat.\\{\\{count\\}\\} unread message\"\n : \"streamChat.\\{\\{count\\}\\} unread messages\"\n ) | translate : { count: unreadCount }\n }}\n </ng-container>\n <ng-template #noUnreadCount>\n {{ \"streamChat.Unread messages\" | translate }}\n </ng-template>\n </div>\n</ng-template>\n" }]
7391
7557
  }], ctorParameters: function () { return [{ type: ChannelService }, { type: ChatClientService }, { type: CustomTemplatesService }, { type: DateParserService }, { type: i0.NgZone }, { type: i0.ChangeDetectorRef }]; }, propDecorators: { mode: [{
7392
7558
  type: Input
7393
7559
  }], direction: [{
@@ -7499,7 +7665,9 @@ StreamChatModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", versio
7499
7665
  MessageBouncePromptComponent,
7500
7666
  VoiceRecordingComponent,
7501
7667
  VoiceRecordingWavebarComponent,
7502
- MessageReactionsSelectorComponent], imports: [CommonModule,
7668
+ MessageReactionsSelectorComponent,
7669
+ UserListComponent,
7670
+ PaginatedListComponent], imports: [CommonModule,
7503
7671
  NgxFloatUiModule,
7504
7672
  StreamAvatarModule,
7505
7673
  TranslateModule], exports: [ChannelComponent,
@@ -7525,7 +7693,9 @@ StreamChatModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", versio
7525
7693
  MessageBouncePromptComponent,
7526
7694
  VoiceRecordingComponent,
7527
7695
  VoiceRecordingWavebarComponent,
7528
- MessageReactionsSelectorComponent] });
7696
+ MessageReactionsSelectorComponent,
7697
+ UserListComponent,
7698
+ PaginatedListComponent] });
7529
7699
  StreamChatModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "15.0.4", ngImport: i0, type: StreamChatModule, imports: [CommonModule,
7530
7700
  NgxFloatUiModule,
7531
7701
  StreamAvatarModule,
@@ -7558,6 +7728,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.4", ngImpor
7558
7728
  VoiceRecordingComponent,
7559
7729
  VoiceRecordingWavebarComponent,
7560
7730
  MessageReactionsSelectorComponent,
7731
+ UserListComponent,
7732
+ PaginatedListComponent,
7561
7733
  ],
7562
7734
  imports: [
7563
7735
  CommonModule,
@@ -7590,6 +7762,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.4", ngImpor
7590
7762
  VoiceRecordingComponent,
7591
7763
  VoiceRecordingWavebarComponent,
7592
7764
  MessageReactionsSelectorComponent,
7765
+ UserListComponent,
7766
+ PaginatedListComponent,
7593
7767
  ],
7594
7768
  }]
7595
7769
  }] });
@@ -7652,5 +7826,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.4", ngImpor
7652
7826
  * Generated bundle index. Do not edit.
7653
7827
  */
7654
7828
 
7655
- export { AttachmentConfigurationService, AttachmentListComponent, AttachmentPreviewListComponent, AttachmentService, AutocompleteTextareaComponent, AvatarComponent, AvatarPlaceholderComponent, ChannelComponent, ChannelHeaderComponent, ChannelListComponent, ChannelPreviewComponent, ChannelQuery, ChannelService, ChatClientService, CustomTemplatesService, DateParserService, EmojiInputService, IconComponent, IconPlaceholderComponent, LoadingIndicatorComponent, LoadingIndicatorPlaceholderComponent, MessageActionsBoxComponent, MessageActionsService, MessageBouncePromptComponent, MessageComponent, MessageInputComponent, MessageInputConfigService, MessageListComponent, MessageReactionsComponent, MessageReactionsSelectorComponent, MessageReactionsService, MessageService, ModalComponent, NotificationComponent, NotificationListComponent, NotificationService, StreamAutocompleteTextareaModule, StreamAvatarModule, StreamChatModule, StreamI18nService, StreamTextareaModule, TextareaComponent, TextareaDirective, ThemeService, ThreadComponent, TransliterationService, VirtualizedListService, VirtualizedMessageListService, VoiceRecordingComponent, VoiceRecordingWavebarComponent, createMessagePreview, getChannelDisplayText, getGroupStyles, getMessageTranslation, getReadBy, isImageAttachment, isImageFile, isOnSeparateDate, listUsers, parseDate, textareaInjectionToken };
7829
+ export { AttachmentConfigurationService, AttachmentListComponent, AttachmentPreviewListComponent, AttachmentService, AutocompleteTextareaComponent, AvatarComponent, AvatarPlaceholderComponent, ChannelComponent, ChannelHeaderComponent, ChannelListComponent, ChannelPreviewComponent, ChannelQuery, ChannelService, ChatClientService, CustomTemplatesService, DateParserService, EmojiInputService, IconComponent, IconPlaceholderComponent, LoadingIndicatorComponent, LoadingIndicatorPlaceholderComponent, MessageActionsBoxComponent, MessageActionsService, MessageBouncePromptComponent, MessageComponent, MessageInputComponent, MessageInputConfigService, MessageListComponent, MessageReactionsComponent, MessageReactionsSelectorComponent, MessageReactionsService, MessageService, ModalComponent, NotificationComponent, NotificationListComponent, NotificationService, PaginatedListComponent, StreamAutocompleteTextareaModule, StreamAvatarModule, StreamChatModule, StreamI18nService, StreamTextareaModule, TextareaComponent, TextareaDirective, ThemeService, ThreadComponent, TransliterationService, UserListComponent, VirtualizedListService, VirtualizedMessageListService, VoiceRecordingComponent, VoiceRecordingWavebarComponent, createMessagePreview, getChannelDisplayText, getGroupStyles, getMessageTranslation, getReadBy, isImageAttachment, isImageFile, isOnSeparateDate, listUsers, parseDate, textareaInjectionToken };
7656
7830
  //# sourceMappingURL=stream-chat-angular.mjs.map