stream-chat-angular 4.59.3 → 4.60.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/i18n/en.d.ts +2 -0
  2. package/assets/version.d.ts +1 -1
  3. package/bundles/stream-chat-angular.umd.js +346 -172
  4. package/bundles/stream-chat-angular.umd.js.map +1 -1
  5. package/esm2015/assets/i18n/en.js +3 -1
  6. package/esm2015/assets/version.js +2 -2
  7. package/esm2015/lib/channel/channel.component.js +13 -9
  8. package/esm2015/lib/channel.service.js +24 -2
  9. package/esm2015/lib/custom-templates.service.js +9 -1
  10. package/esm2015/lib/edit-message-form/edit-message-form.component.js +87 -0
  11. package/esm2015/lib/message/message.component.js +16 -25
  12. package/esm2015/lib/message-actions-box/message-actions-box.component.js +6 -46
  13. package/esm2015/lib/message-bounce-prompt/message-bounce-prompt.component.js +80 -0
  14. package/esm2015/lib/message-list/message-list.component.js +14 -8
  15. package/esm2015/lib/stream-chat.module.js +13 -3
  16. package/esm2015/lib/types.js +1 -1
  17. package/esm2015/public-api.js +3 -1
  18. package/fesm2015/stream-chat-angular.js +318 -168
  19. package/fesm2015/stream-chat-angular.js.map +1 -1
  20. package/lib/channel/channel.component.d.ts +3 -1
  21. package/lib/channel.service.d.ts +10 -9
  22. package/lib/custom-templates.service.d.ts +8 -0
  23. package/lib/edit-message-form/edit-message-form.component.d.ts +31 -0
  24. package/lib/message/message.component.d.ts +2 -1
  25. package/lib/message-actions-box/message-actions-box.component.d.ts +2 -11
  26. package/lib/message-bounce-prompt/message-bounce-prompt.component.d.ts +28 -0
  27. package/lib/stream-chat.module.d.ts +7 -5
  28. package/lib/types.d.ts +0 -6
  29. package/package.json +1 -1
  30. package/public-api.d.ts +2 -0
  31. package/src/assets/i18n/en.ts +3 -0
  32. package/src/assets/styles/css/index.css +1 -1
  33. package/src/assets/styles/scss/Message.scss +21 -17
  34. package/src/assets/styles/scss/MessageActions.scss +0 -9
  35. package/src/assets/styles/scss/_base.scss +8 -1
  36. package/src/assets/styles/v2/css/index.css +1 -1
  37. package/src/assets/styles/v2/css/index.layout.css +1 -1
  38. package/src/assets/styles/v2/scss/AttachmentList/AttachmentList-layout.scss +6 -0
  39. package/src/assets/styles/v2/scss/EditMessageForm/EditMessageForm-layout.scss +13 -15
  40. package/src/assets/styles/v2/scss/Message/Message-layout.scss +14 -3
  41. package/src/assets/styles/v2/scss/MessageActionsBox/MessageActionsBox-layout.scss +0 -8
  42. package/src/assets/styles/v2/scss/_utils.scss +0 -1
  43. package/src/assets/version.ts +1 -1
@@ -356,7 +356,7 @@
356
356
  return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
357
357
  }
358
358
 
359
- var version = '4.59.3';
359
+ var version = '4.60.0';
360
360
 
361
361
  /**
362
362
  * The `NotificationService` can be used to add or remove notifications. By default the [`NotificationList`](../components/NotificationListComponent.mdx) component displays the currently active notifications.
@@ -785,6 +785,7 @@
785
785
  var channel = _this.activeChannelSubject.getValue();
786
786
  return messages.map(function (message) { return _this.transformToStreamMessage(message, channel); });
787
787
  }), operators.shareReplay(1));
788
+ this.bouncedMessage$ = new rxjs.BehaviorSubject(undefined);
788
789
  this.hasMoreChannels$ = this.hasMoreChannelsSubject
789
790
  .asObservable()
790
791
  .pipe(operators.shareReplay(1));
@@ -1213,11 +1214,20 @@
1213
1214
  case 1:
1214
1215
  messageToUpdate = _h.sent();
1215
1216
  _h.label = 2;
1216
- case 2: return [4 /*yield*/, this.chatClientService.chatClient.updateMessage(messageToUpdate)];
1217
+ case 2:
1218
+ if (message.moderation_details) {
1219
+ return [2 /*return*/, this.resendMessage(message)];
1220
+ }
1221
+ return [4 /*yield*/, this.chatClientService.chatClient.updateMessage(messageToUpdate)];
1217
1222
  case 3:
1218
1223
  response = _h.sent();
1219
1224
  channel = (_a = this.channelsSubject
1220
1225
  .getValue()) === null || _a === void 0 ? void 0 : _a.find(function (c) { return c.cid === message.cid; });
1226
+ if (response.message.type === 'error' &&
1227
+ response.message.moderation_details) {
1228
+ this.notificationService.addTemporaryNotification('streamChat.This message did not meet our content guidelines');
1229
+ return [2 /*return*/, message];
1230
+ }
1221
1231
  return [2 /*return*/, this.transformToStreamMessage(response.message, channel)];
1222
1232
  }
1223
1233
  });
@@ -1226,13 +1236,27 @@
1226
1236
  /**
1227
1237
  * Deletes the message from the active channel
1228
1238
  * @param message Message to be deleted
1239
+ * @param isLocalDelete set this `true` if you want to delete a message that's only part of the local state, not yet saved on the backend
1229
1240
  */
1230
- ChannelService.prototype.deleteMessage = function (message) {
1241
+ ChannelService.prototype.deleteMessage = function (message, isLocalDelete) {
1242
+ if (isLocalDelete === void 0) { isLocalDelete = false; }
1231
1243
  return __awaiter(this, void 0, void 0, function () {
1232
- var result;
1244
+ var result, result;
1233
1245
  return __generator(this, function (_h) {
1234
1246
  switch (_h.label) {
1235
1247
  case 0:
1248
+ if (isLocalDelete && this.activeChannel) {
1249
+ result = this.activeChannel.state.removeMessage({
1250
+ id: message.id,
1251
+ parent_id: message.parent_id,
1252
+ });
1253
+ if (result) {
1254
+ message.parent_id
1255
+ ? this.activeThreadMessagesSubject.next(this.activeChannel.state.threads[message.parent_id])
1256
+ : this.activeChannelMessagesSubject.next(this.activeChannel.state.messages);
1257
+ }
1258
+ return [2 /*return*/];
1259
+ }
1236
1260
  if (!this.messageDeleteConfirmationHandler) return [3 /*break*/, 4];
1237
1261
  return [4 /*yield*/, this.messageDeleteConfirmationHandler(message)];
1238
1262
  case 1:
@@ -3152,6 +3176,8 @@
3152
3176
  'Unread messages': 'Unread messages',
3153
3177
  '{{count}} unread messages': '{{count}} unread messages',
3154
3178
  '{{count}} unread message': '{{count}} unread message',
3179
+ 'This message did not meet our content guidelines': 'This message did not meet our content guidelines',
3180
+ 'Send Anyway': 'Send Anyway',
3155
3181
  },
3156
3182
  };
3157
3183
 
@@ -3574,6 +3600,14 @@
3574
3600
  * The template to show if the thread message list is empty
3575
3601
  */
3576
3602
  this.emptyThreadMessageListPlaceholder$ = new rxjs.BehaviorSubject(undefined);
3603
+ /**
3604
+ * The template used to display the [edit message form](../components/EditMessageFormComponent.mdx)
3605
+ */
3606
+ this.editMessageFormTemplate$ = new rxjs.BehaviorSubject(undefined);
3607
+ /**
3608
+ * The template used to display the [message bounce prompt](../components/MessageBouncePromptComponent.mdx)
3609
+ */
3610
+ this.messageBouncePromptTemplate$ = new rxjs.BehaviorSubject(undefined);
3577
3611
  }
3578
3612
  return CustomTemplatesService;
3579
3613
  }());
@@ -3913,6 +3947,137 @@
3913
3947
  }]
3914
3948
  }], ctorParameters: function () { return [{ type: ChatClientService }, { type: NotificationService }, { type: ChannelService }]; } });
3915
3949
 
3950
+ /**
3951
+ * The `MessageActionsBox` component displays a list of message actions (i.e edit), that can be opened or closed. You can find the [list of the supported actions](../concepts/message-interactions.mdx) in the message interaction guide.
3952
+ */
3953
+ var MessageActionsBoxComponent = /** @class */ (function () {
3954
+ function MessageActionsBoxComponent(customTemplatesService, messageActionsService, cdRef) {
3955
+ this.customTemplatesService = customTemplatesService;
3956
+ this.messageActionsService = messageActionsService;
3957
+ this.cdRef = cdRef;
3958
+ /**
3959
+ * Indicates if the list should be opened or closed. Adding a UI element to open and close the list is the parent's component responsibility.
3960
+ * @deprecated No need for this since [theme-v2](../theming/introduction.mdx)
3961
+ */
3962
+ this.isOpen = false;
3963
+ /**
3964
+ * Indicates if the message actions are belonging to a message that was sent by the current user or not.
3965
+ */
3966
+ this.isMine = false;
3967
+ /**
3968
+ * The list of [channel capabilities](https://getstream.io/chat/docs/javascript/channel_capabilities/?language=javascript) that are enabled for the current user, the list of [supported interactions](../concepts/message-interactions.mdx) can be found in our message interaction guide. Unathorized actions won't be displayed on the UI.
3969
+ */
3970
+ this.enabledActions = [];
3971
+ /**
3972
+ * A list of custom message actions to be displayed in the action box
3973
+ *
3974
+ * In the next major release this will be released with `messageReactionsService.customActions$`
3975
+ *
3976
+ * More information: https://getstream.io/chat/docs/sdk/angular/services/MessageActionsService
3977
+ */
3978
+ this.customActions = [];
3979
+ /**
3980
+ * The number of authorized actions (it can be less or equal than the number of enabled actions)
3981
+ *
3982
+ * @deprecated components should use `messageReactionsService.getAuthorizedMessageActionsCount` method
3983
+ *
3984
+ * More information: https://getstream.io/chat/docs/sdk/angular/services/MessageActionsService
3985
+ */
3986
+ this.displayedActionsCount = new i0.EventEmitter();
3987
+ /**
3988
+ * An event which emits `true` if the edit message modal is open, and `false` when it is closed.
3989
+ *
3990
+ * @deprecated components should use `messageReactionsService.messageToEdit$` Observable
3991
+ *
3992
+ * More information: https://getstream.io/chat/docs/sdk/angular/services/MessageActionsService
3993
+ */
3994
+ this.isEditing = new i0.EventEmitter();
3995
+ this.visibleMessageActionItems = [];
3996
+ this.isEditModalOpen = false;
3997
+ this.subscriptions = [];
3998
+ this.isViewInited = false;
3999
+ this.messageActionItems = this.messageActionsService.defaultActions;
4000
+ }
4001
+ MessageActionsBoxComponent.prototype.ngOnInit = function () {
4002
+ var _this = this;
4003
+ this.subscriptions.push(this.messageActionsService.messageToEdit$.subscribe(function (m) {
4004
+ var _a;
4005
+ var isEditModalOpen = false;
4006
+ if (m && m.id === ((_a = _this.message) === null || _a === void 0 ? void 0 : _a.id)) {
4007
+ isEditModalOpen = true;
4008
+ }
4009
+ if (isEditModalOpen !== _this.isEditModalOpen) {
4010
+ _this.isEditModalOpen = isEditModalOpen;
4011
+ _this.isEditing.emit(_this.isEditModalOpen);
4012
+ if (_this.isViewInited) {
4013
+ _this.cdRef.detectChanges();
4014
+ }
4015
+ }
4016
+ }));
4017
+ };
4018
+ MessageActionsBoxComponent.prototype.ngOnChanges = function (changes) {
4019
+ if (changes.isMine ||
4020
+ changes.enabledActions ||
4021
+ changes.message ||
4022
+ changes.customActions) {
4023
+ this.setVisibleActions();
4024
+ }
4025
+ };
4026
+ MessageActionsBoxComponent.prototype.ngAfterViewInit = function () {
4027
+ this.isViewInited = true;
4028
+ };
4029
+ MessageActionsBoxComponent.prototype.ngOnDestroy = function () {
4030
+ this.subscriptions.forEach(function (s) { return s.unsubscribe(); });
4031
+ };
4032
+ MessageActionsBoxComponent.prototype.getActionLabel = function (actionLabelOrTranslationKey) {
4033
+ return typeof actionLabelOrTranslationKey === 'string'
4034
+ ? actionLabelOrTranslationKey
4035
+ : actionLabelOrTranslationKey(this.message);
4036
+ };
4037
+ MessageActionsBoxComponent.prototype.getMessageActionTemplateContext = function (item) {
4038
+ return {
4039
+ actionHandler: item.actionHandler,
4040
+ isMine: this.isMine,
4041
+ actionName: item.actionName,
4042
+ message: this.message,
4043
+ actionLabelOrTranslationKey: item.actionLabelOrTranslationKey,
4044
+ };
4045
+ };
4046
+ MessageActionsBoxComponent.prototype.trackByActionName = function (_, item) {
4047
+ return item.actionName;
4048
+ };
4049
+ MessageActionsBoxComponent.prototype.setVisibleActions = function () {
4050
+ var _this = this;
4051
+ this.visibleMessageActionItems = __spreadArray(__spreadArray([], __read(this.messageActionItems)), __read(this.customActions)).filter(function (item) { return item.isVisible(_this.enabledActions, _this.isMine, _this.message); });
4052
+ this.displayedActionsCount.emit(this.visibleMessageActionItems.length);
4053
+ };
4054
+ return MessageActionsBoxComponent;
4055
+ }());
4056
+ MessageActionsBoxComponent.ɵfac = i0__namespace.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0__namespace, type: MessageActionsBoxComponent, deps: [{ token: CustomTemplatesService }, { token: MessageActionsService }, { token: i0__namespace.ChangeDetectorRef }], target: i0__namespace.ɵɵFactoryTarget.Component });
4057
+ MessageActionsBoxComponent.ɵcmp = i0__namespace.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.5", type: MessageActionsBoxComponent, selector: "stream-message-actions-box", inputs: { isOpen: "isOpen", isMine: "isMine", message: "message", enabledActions: "enabledActions", customActions: "customActions" }, outputs: { displayedActionsCount: "displayedActionsCount", isEditing: "isEditing" }, usesOnChanges: true, ngImport: i0__namespace, template: "<div\n #actionBox\n data-testid=\"action-box\"\n class=\"str-chat__message-actions-box str-chat__message-actions-box-angular\"\n [class.str-chat__message-actions-box--open]=\"true\"\n>\n <ul class=\"str-chat__message-actions-list\">\n <ng-container\n *ngFor=\"let item of visibleMessageActionItems; trackBy: trackByActionName\"\n >\n <ng-container\n *ngTemplateOutlet=\"\n (customTemplatesService.messageActionsBoxItemTemplate$ | async) ||\n defaultMessageActionItem;\n context: getMessageActionTemplateContext(item)\n \"\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>\n <button\n class=\"str-chat__message-actions-list-item-button\"\n [attr.data-testid]=\"actionName + '-action'\"\n (click)=\"actionHandler(message, isMine)\"\n >\n <li class=\"str-chat__message-actions-list-item\">\n {{ getActionLabel(actionLabelOrTranslationKey) | translate }}\n </li>\n </button>\n</ng-template>\n", directives: [{ type: i5__namespace.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i5__namespace.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet"] }], pipes: { "async": i5__namespace.AsyncPipe, "translate": i6__namespace.TranslatePipe } });
4058
+ i0__namespace.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0__namespace, type: MessageActionsBoxComponent, decorators: [{
4059
+ type: i0.Component,
4060
+ args: [{
4061
+ selector: 'stream-message-actions-box',
4062
+ templateUrl: './message-actions-box.component.html',
4063
+ styles: [],
4064
+ }]
4065
+ }], ctorParameters: function () { return [{ type: CustomTemplatesService }, { type: MessageActionsService }, { type: i0__namespace.ChangeDetectorRef }]; }, propDecorators: { isOpen: [{
4066
+ type: i0.Input
4067
+ }], isMine: [{
4068
+ type: i0.Input
4069
+ }], message: [{
4070
+ type: i0.Input
4071
+ }], enabledActions: [{
4072
+ type: i0.Input
4073
+ }], customActions: [{
4074
+ type: i0.Input
4075
+ }], displayedActionsCount: [{
4076
+ type: i0.Output
4077
+ }], isEditing: [{
4078
+ type: i0.Output
4079
+ }] } });
4080
+
3916
4081
  /**
3917
4082
  * The `Modal` component displays its content in an overlay. The modal can be closed with a close button, if the user clicks outside of the modal content, or if the escape button is pressed. The modal can also be closed from outside.
3918
4083
  */
@@ -4927,115 +5092,52 @@
4927
5092
  }], ctorParameters: function () { return [{ type: CustomTemplatesService }, { type: NotificationService }, { type: ThemeService }]; } });
4928
5093
 
4929
5094
  /**
4930
- * The `MessageActionsBox` component displays a list of message actions (i.e edit), that can be opened or closed. You can find the [list of the supported actions](../concepts/message-interactions.mdx) in the message interaction guide.
5095
+ * The edit message form displays a modal that's opened when a user edits a message. The component uses the [`MessageActionsService`](../../services/MessageActionsService) to know which message is being edited.
5096
+ *
5097
+ * By default this is displayed within the [`stream-channel` component](../../components/ChannelComponent).
4931
5098
  */
4932
- var MessageActionsBoxComponent = /** @class */ (function () {
4933
- function MessageActionsBoxComponent(customTemplatesService, messageActionsService, cdRef) {
4934
- var _this = this;
5099
+ var EditMessageFormComponent = /** @class */ (function () {
5100
+ function EditMessageFormComponent(customTemplatesService, messageActionsService) {
4935
5101
  this.customTemplatesService = customTemplatesService;
4936
5102
  this.messageActionsService = messageActionsService;
4937
- this.cdRef = cdRef;
4938
- /**
4939
- * Indicates if the list should be opened or closed. Adding a UI element to open and close the list is the parent's component responsibility.
4940
- * @deprecated No need for this since [theme-v2](../theming/introduction.mdx)
4941
- */
4942
- this.isOpen = false;
4943
- /**
4944
- * Indicates if the message actions are belonging to a message that was sent by the current user or not.
4945
- */
4946
- this.isMine = false;
4947
- /**
4948
- * The list of [channel capabilities](https://getstream.io/chat/docs/javascript/channel_capabilities/?language=javascript) that are enabled for the current user, the list of [supported interactions](../concepts/message-interactions.mdx) can be found in our message interaction guide. Unathorized actions won't be displayed on the UI.
4949
- */
4950
- this.enabledActions = [];
4951
- /**
4952
- * A list of custom message actions to be displayed in the action box
4953
- *
4954
- * In the next major release this will be released with `messageReactionsService.customActions$`
4955
- *
4956
- * More information: https://getstream.io/chat/docs/sdk/angular/services/MessageActionsService
4957
- */
4958
- this.customActions = [];
4959
- /**
4960
- * The number of authorized actions (it can be less or equal than the number of enabled actions)
4961
- *
4962
- * @deprecated components should use `messageReactionsService.getAuthorizedMessageActionsCount` method
4963
- *
4964
- * More information: https://getstream.io/chat/docs/sdk/angular/services/MessageActionsService
4965
- */
4966
- this.displayedActionsCount = new i0.EventEmitter();
4967
- /**
4968
- * An event which emits `true` if the edit message modal is open, and `false` when it is closed.
4969
- *
4970
- * @deprecated components should use `messageReactionsService.messageToEdit$` Observable
4971
- *
4972
- * More information: https://getstream.io/chat/docs/sdk/angular/services/MessageActionsService
4973
- */
4974
- this.isEditing = new i0.EventEmitter();
4975
- this.isEditModalOpen = false;
4976
- this.visibleMessageActionItems = [];
5103
+ this.class = 'str-chat-angular__edit-message-form';
5104
+ this.isModalOpen = false;
4977
5105
  this.sendMessageSubject = new rxjs.Subject();
4978
5106
  this.subscriptions = [];
4979
- this.isViewInited = false;
4980
- this.modalClosed = function () {
4981
- _this.isEditModalOpen = false;
4982
- _this.messageActionsService.messageToEdit$.next(undefined);
4983
- };
4984
- this.messageActionItems = this.messageActionsService.defaultActions;
4985
5107
  this.sendMessage$ = this.sendMessageSubject.asObservable();
4986
5108
  }
4987
- MessageActionsBoxComponent.prototype.ngOnInit = function () {
5109
+ EditMessageFormComponent.prototype.ngOnInit = function () {
4988
5110
  var _this = this;
4989
- this.subscriptions.push(this.messageActionsService.messageToEdit$.subscribe(function (m) {
4990
- var _a;
4991
- var isEditModalOpen = false;
4992
- if (m && m.id === ((_a = _this.message) === null || _a === void 0 ? void 0 : _a.id)) {
4993
- isEditModalOpen = true;
4994
- }
4995
- if (isEditModalOpen !== _this.isEditModalOpen) {
4996
- _this.isEditModalOpen = isEditModalOpen;
4997
- _this.isEditing.emit(_this.isEditModalOpen);
4998
- if (_this.isViewInited) {
4999
- _this.cdRef.detectChanges();
5000
- }
5111
+ this.messageActionsService.messageToEdit$.subscribe(function (message) {
5112
+ if ((message && !_this.isModalOpen) || (!message && _this.isModalOpen)) {
5113
+ _this.message = message;
5114
+ _this.isModalOpen = !!message;
5001
5115
  }
5002
- }));
5003
- };
5004
- MessageActionsBoxComponent.prototype.ngOnChanges = function (changes) {
5005
- if (changes.isMine ||
5006
- changes.enabledActions ||
5007
- changes.message ||
5008
- changes.customActions) {
5009
- this.setVisibleActions();
5010
- }
5011
- };
5012
- MessageActionsBoxComponent.prototype.ngAfterViewInit = function () {
5013
- this.isViewInited = true;
5116
+ });
5014
5117
  };
5015
- MessageActionsBoxComponent.prototype.ngOnDestroy = function () {
5118
+ EditMessageFormComponent.prototype.ngOnDestroy = function () {
5016
5119
  this.subscriptions.forEach(function (s) { return s.unsubscribe(); });
5017
5120
  };
5018
- MessageActionsBoxComponent.prototype.getActionLabel = function (actionLabelOrTranslationKey) {
5019
- return typeof actionLabelOrTranslationKey === 'string'
5020
- ? actionLabelOrTranslationKey
5021
- : actionLabelOrTranslationKey(this.message);
5022
- };
5023
- MessageActionsBoxComponent.prototype.getMessageActionTemplateContext = function (item) {
5121
+ EditMessageFormComponent.prototype.getEditModalContext = function () {
5122
+ var _this = this;
5024
5123
  return {
5025
- actionHandler: item.actionHandler,
5026
- isMine: this.isMine,
5027
- actionName: item.actionName,
5028
- message: this.message,
5029
- actionLabelOrTranslationKey: item.actionLabelOrTranslationKey,
5124
+ isOpen: this.isModalOpen,
5125
+ isOpenChangeHandler: function (isOpen) {
5126
+ _this.isModalOpen = isOpen;
5127
+ if (!_this.isModalOpen) {
5128
+ _this.dismissed();
5129
+ }
5130
+ },
5131
+ content: this.modalContent,
5030
5132
  };
5031
5133
  };
5032
- MessageActionsBoxComponent.prototype.sendClicked = function () {
5033
- this.sendMessageSubject.next();
5034
- };
5035
- MessageActionsBoxComponent.prototype.getMessageInputContext = function () {
5134
+ EditMessageFormComponent.prototype.getMessageInputContext = function () {
5135
+ var _this = this;
5036
5136
  return {
5037
5137
  message: this.message,
5038
- messageUpdateHandler: this.modalClosed,
5138
+ messageUpdateHandler: function () {
5139
+ _this.dismissed();
5140
+ },
5039
5141
  isFileUploadEnabled: undefined,
5040
5142
  areMentionsEnabled: undefined,
5041
5143
  isMultipleFileUploadEnabled: undefined,
@@ -5044,64 +5146,129 @@
5044
5146
  sendMessage$: this.sendMessage$,
5045
5147
  };
5046
5148
  };
5047
- MessageActionsBoxComponent.prototype.getEditModalContext = function () {
5149
+ EditMessageFormComponent.prototype.sendClicked = function () {
5150
+ this.sendMessageSubject.next();
5151
+ };
5152
+ EditMessageFormComponent.prototype.dismissed = function () {
5153
+ this.isModalOpen = false;
5154
+ this.message = undefined;
5155
+ this.messageActionsService.messageToEdit$.next(undefined);
5156
+ };
5157
+ return EditMessageFormComponent;
5158
+ }());
5159
+ EditMessageFormComponent.ɵfac = i0__namespace.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0__namespace, type: EditMessageFormComponent, deps: [{ token: CustomTemplatesService }, { token: MessageActionsService }], target: i0__namespace.ɵɵFactoryTarget.Component });
5160
+ EditMessageFormComponent.ɵcmp = i0__namespace.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.5", type: EditMessageFormComponent, selector: "stream-edit-message-form", host: { properties: { "class": "this.class" } }, viewQueries: [{ propertyName: "modalContent", first: true, predicate: ["editMessageForm"], descendants: true, static: true }], ngImport: i0__namespace, template: "<ng-container\n *ngTemplateOutlet=\"\n (customTemplatesService.modalTemplate$ | async) || defaultModal;\n context: getEditModalContext()\n \"\n></ng-container>\n\n<ng-template\n #defaultModal\n let-isOpen=\"isOpen\"\n let-isOpenChangeHandler=\"isOpenChangeHandler\"\n let-content=\"content\"\n>\n <stream-modal\n [isOpen]=\"isOpen\"\n *ngIf=\"isOpen\"\n (isOpenChange)=\"isOpenChangeHandler($event)\"\n [content]=\"content\"\n >\n </stream-modal>\n</ng-template>\n\n<ng-template #editMessageForm>\n <div class=\"str-chat__edit-message-form\">\n <ng-template\n #defaultInput\n let-messageInput=\"message\"\n let-messageUpdateHandler=\"messageUpdateHandler\"\n let-sendMessage$Input=\"sendMessage$\"\n >\n <stream-message-input\n [message]=\"messageInput\"\n (messageUpdate)=\"messageUpdateHandler()\"\n [sendMessage$]=\"sendMessage$Input\"\n ></stream-message-input>\n </ng-template>\n <ng-container\n *ngTemplateOutlet=\"\n (customTemplatesService.messageInputTemplate$ | async) || defaultInput;\n context: getMessageInputContext()\n \"\n >\n </ng-container>\n\n <stream-notification-list></stream-notification-list>\n <div\n class=\"\n str-chat__message-team-form-footer\n str-chat__message-team-form-footer-angular\n \"\n >\n <div class=\"str-chat__edit-message-form-options\">\n <button\n class=\"str-chat__edit-message-cancel\"\n translate\n data-testid=\"cancel-button\"\n (click)=\"dismissed()\"\n >\n streamChat.Cancel\n </button>\n <button\n type=\"submit\"\n translate\n class=\"str-chat__edit-message-send\"\n data-testid=\"send-button\"\n (click)=\"sendClicked()\"\n (keyup.enter)=\"sendClicked()\"\n >\n streamChat.Send\n </button>\n </div>\n </div>\n </div>\n</ng-template>\n", components: [{ type: ModalComponent, selector: "stream-modal", inputs: ["isOpen", "content"], outputs: ["isOpenChange"] }, { type: MessageInputComponent, selector: "stream-message-input", inputs: ["isFileUploadEnabled", "areMentionsEnabled", "mentionScope", "mode", "isMultipleFileUploadEnabled", "message", "sendMessage$", "inputMode", "autoFocus"], outputs: ["messageUpdate"] }, { type: NotificationListComponent, selector: "stream-notification-list" }], directives: [{ type: i5__namespace.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet"] }, { type: i5__namespace.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i6__namespace.TranslateDirective, selector: "[translate],[ngx-translate]", inputs: ["translate", "translateParams"] }], pipes: { "async": i5__namespace.AsyncPipe } });
5161
+ i0__namespace.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0__namespace, type: EditMessageFormComponent, decorators: [{
5162
+ type: i0.Component,
5163
+ args: [{
5164
+ selector: 'stream-edit-message-form',
5165
+ templateUrl: './edit-message-form.component.html',
5166
+ styles: [],
5167
+ }]
5168
+ }], ctorParameters: function () { return [{ type: CustomTemplatesService }, { type: MessageActionsService }]; }, propDecorators: { class: [{
5169
+ type: i0.HostBinding
5170
+ }], modalContent: [{
5171
+ type: i0.ViewChild,
5172
+ args: ['editMessageForm', { static: true }]
5173
+ }] } });
5174
+
5175
+ /**
5176
+ * The component watches for the [`channelService.bouncedMessage$` stream](../../services/ChannelService/#bouncedmessage) and opens the bounce modal if a message is emitted.
5177
+ *
5178
+ * To bounce messages, you need to set up [semantic filters for moderation](https://getstream.io/automated-moderation/docs/automod_configuration/?q=semantic%20filters).
5179
+ */
5180
+ var MessageBouncePromptComponent = /** @class */ (function () {
5181
+ function MessageBouncePromptComponent(channelService, customTemplatesService, messageActionsService) {
5048
5182
  var _this = this;
5049
- return {
5050
- isOpen: this.isEditModalOpen,
5051
- isOpenChangeHandler: function (isOpen) {
5052
- _this.isEditModalOpen = isOpen;
5053
- if (!_this.isEditModalOpen) {
5054
- _this.modalClosed();
5055
- }
5056
- },
5057
- content: this.modalContent,
5183
+ this.channelService = channelService;
5184
+ this.customTemplatesService = customTemplatesService;
5185
+ this.messageActionsService = messageActionsService;
5186
+ this.class = 'str-chat__message-bounce-prompt';
5187
+ this.isModalOpen = false;
5188
+ this.subscriptions = [];
5189
+ this.messageBounceModalOpenChanged = function (isOpen) {
5190
+ _this.isModalOpen = isOpen;
5191
+ if (!isOpen) {
5192
+ _this.message = undefined;
5193
+ _this.channelService.bouncedMessage$.next(undefined);
5194
+ }
5058
5195
  };
5196
+ this.subscriptions.push(this.channelService.bouncedMessage$.subscribe(function (m) {
5197
+ if (m !== _this.message) {
5198
+ _this.message = m;
5199
+ if (_this.message) {
5200
+ _this.isModalOpen = true;
5201
+ }
5202
+ }
5203
+ }));
5204
+ }
5205
+ MessageBouncePromptComponent.prototype.ngOnDestroy = function () {
5206
+ this.subscriptions.forEach(function (s) { return s.unsubscribe(); });
5059
5207
  };
5060
- MessageActionsBoxComponent.prototype.trackByActionName = function (_, item) {
5061
- return item.actionName;
5208
+ MessageBouncePromptComponent.prototype.resendMessage = function () {
5209
+ return __awaiter(this, void 0, void 0, function () {
5210
+ return __generator(this, function (_a) {
5211
+ switch (_a.label) {
5212
+ case 0:
5213
+ this.isModalOpen = false;
5214
+ return [4 /*yield*/, this.channelService.resendMessage(this.message)];
5215
+ case 1:
5216
+ _a.sent();
5217
+ this.message = undefined;
5218
+ this.channelService.bouncedMessage$.next(undefined);
5219
+ return [2 /*return*/];
5220
+ }
5221
+ });
5222
+ });
5062
5223
  };
5063
- MessageActionsBoxComponent.prototype.setVisibleActions = function () {
5064
- var _this = this;
5065
- this.visibleMessageActionItems = __spreadArray(__spreadArray([], __read(this.messageActionItems)), __read(this.customActions)).filter(function (item) { return item.isVisible(_this.enabledActions, _this.isMine, _this.message); });
5066
- this.displayedActionsCount.emit(this.visibleMessageActionItems.length);
5224
+ MessageBouncePromptComponent.prototype.deleteMessage = function () {
5225
+ return __awaiter(this, void 0, void 0, function () {
5226
+ return __generator(this, function (_a) {
5227
+ switch (_a.label) {
5228
+ case 0:
5229
+ if (!this.message) {
5230
+ return [2 /*return*/];
5231
+ }
5232
+ this.isModalOpen = false;
5233
+ return [4 /*yield*/, this.channelService.deleteMessage(this.message, true)];
5234
+ case 1:
5235
+ _a.sent();
5236
+ this.message = undefined;
5237
+ this.channelService.bouncedMessage$.next(undefined);
5238
+ return [2 /*return*/];
5239
+ }
5240
+ });
5241
+ });
5067
5242
  };
5068
- return MessageActionsBoxComponent;
5243
+ MessageBouncePromptComponent.prototype.editMessage = function () {
5244
+ this.isModalOpen = false;
5245
+ this.messageActionsService.messageToEdit$.next(this.message);
5246
+ this.message = undefined;
5247
+ this.channelService.bouncedMessage$.next(undefined);
5248
+ };
5249
+ return MessageBouncePromptComponent;
5069
5250
  }());
5070
- MessageActionsBoxComponent.ɵfac = i0__namespace.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0__namespace, type: MessageActionsBoxComponent, deps: [{ token: CustomTemplatesService }, { token: MessageActionsService }, { token: i0__namespace.ChangeDetectorRef }], target: i0__namespace.ɵɵFactoryTarget.Component });
5071
- MessageActionsBoxComponent.ɵcmp = i0__namespace.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.5", type: MessageActionsBoxComponent, selector: "stream-message-actions-box", inputs: { isOpen: "isOpen", isMine: "isMine", message: "message", enabledActions: "enabledActions", customActions: "customActions" }, outputs: { displayedActionsCount: "displayedActionsCount", isEditing: "isEditing" }, viewQueries: [{ propertyName: "modalContent", first: true, predicate: ["modalContent"], descendants: true, static: true }], usesOnChanges: true, ngImport: i0__namespace, template: "<div\n #actionBox\n data-testid=\"action-box\"\n class=\"str-chat__message-actions-box str-chat__message-actions-box-angular\"\n [class.str-chat__message-actions-box--open]=\"true\"\n>\n <ul class=\"str-chat__message-actions-list\">\n <ng-container\n *ngFor=\"let item of visibleMessageActionItems; trackBy: trackByActionName\"\n >\n <ng-container\n *ngTemplateOutlet=\"\n (customTemplatesService.messageActionsBoxItemTemplate$ | async) ||\n defaultMessageActionItem;\n context: getMessageActionTemplateContext(item)\n \"\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>\n <button\n class=\"str-chat__message-actions-list-item-button\"\n [attr.data-testid]=\"actionName + '-action'\"\n (click)=\"actionHandler(message, isMine)\"\n >\n <li class=\"str-chat__message-actions-list-item\">\n {{ getActionLabel(actionLabelOrTranslationKey) | translate }}\n </li>\n </button>\n</ng-template>\n\n<ng-container\n *ngTemplateOutlet=\"\n (customTemplatesService.modalTemplate$ | async) || defaultModal;\n context: getEditModalContext()\n \"\n></ng-container>\n\n<ng-template\n #defaultModal\n let-isOpen=\"isOpen\"\n let-isOpenChangeHandler=\"isOpenChangeHandler\"\n let-content=\"content\"\n>\n <stream-modal\n [isOpen]=\"isOpen\"\n *ngIf=\"isOpen\"\n (isOpenChange)=\"isOpenChangeHandler($event)\"\n [content]=\"content\"\n >\n </stream-modal>\n</ng-template>\n\n<ng-template #modalContent>\n <div class=\"str-chat__edit-message-form\" *ngIf=\"isEditModalOpen\">\n <ng-template\n #defaultInput\n let-messageInput=\"message\"\n let-messageUpdateHandler=\"messageUpdateHandler\"\n let-sendMessage$Input=\"sendMessage$\"\n >\n <stream-message-input\n [message]=\"messageInput\"\n (messageUpdate)=\"messageUpdateHandler()\"\n [sendMessage$]=\"sendMessage$Input\"\n ></stream-message-input>\n </ng-template>\n <ng-container\n *ngTemplateOutlet=\"\n (customTemplatesService.messageInputTemplate$ | async) || defaultInput;\n context: getMessageInputContext()\n \"\n >\n </ng-container>\n\n <stream-notification-list></stream-notification-list>\n <div\n class=\"\n str-chat__message-team-form-footer\n str-chat__message-team-form-footer-angular\n \"\n >\n <div class=\"str-chat__edit-message-form-options\">\n <button\n class=\"str-chat__edit-message-cancel\"\n translate\n data-testid=\"cancel-button\"\n (click)=\"modalClosed()\"\n >\n streamChat.Cancel\n </button>\n <button\n type=\"submit\"\n translate\n class=\"str-chat__edit-message-send\"\n data-testid=\"send-button\"\n (click)=\"sendClicked()\"\n (keyup.enter)=\"sendClicked()\"\n >\n streamChat.Send\n </button>\n </div>\n </div>\n </div>\n</ng-template>\n", components: [{ type: ModalComponent, selector: "stream-modal", inputs: ["isOpen", "content"], outputs: ["isOpenChange"] }, { type: MessageInputComponent, selector: "stream-message-input", inputs: ["isFileUploadEnabled", "areMentionsEnabled", "mentionScope", "mode", "isMultipleFileUploadEnabled", "message", "sendMessage$", "inputMode", "autoFocus"], outputs: ["messageUpdate"] }, { type: NotificationListComponent, selector: "stream-notification-list" }], directives: [{ type: i5__namespace.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i5__namespace.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet"] }, { type: i5__namespace.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i6__namespace.TranslateDirective, selector: "[translate],[ngx-translate]", inputs: ["translate", "translateParams"] }], pipes: { "async": i5__namespace.AsyncPipe, "translate": i6__namespace.TranslatePipe } });
5072
- i0__namespace.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0__namespace, type: MessageActionsBoxComponent, decorators: [{
5251
+ MessageBouncePromptComponent.ɵfac = i0__namespace.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0__namespace, type: MessageBouncePromptComponent, deps: [{ token: ChannelService }, { token: CustomTemplatesService }, { token: MessageActionsService }], target: i0__namespace.ɵɵFactoryTarget.Component });
5252
+ MessageBouncePromptComponent.ɵcmp = i0__namespace.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.5", type: MessageBouncePromptComponent, selector: "stream-message-bounce-prompt", host: { properties: { "class": "this.class" } }, ngImport: i0__namespace, template: "<ng-container\n *ngTemplateOutlet=\"\n (customTemplatesService.modalTemplate$ | async) || defaultModal;\n context: {\n message: message,\n isOpen: isModalOpen,\n isOpenChangeHandler: messageBounceModalOpenChanged,\n content: modalContent\n }\n \"\n></ng-container>\n\n<ng-template\n #defaultModal\n let-isOpen=\"isOpen\"\n let-isOpenChangeHandler=\"isOpenChangeHandler\"\n let-content=\"content\"\n>\n <stream-modal\n [isOpen]=\"isOpen\"\n *ngIf=\"isOpen\"\n (isOpenChange)=\"isOpenChangeHandler($event)\"\n [content]=\"content\"\n >\n </stream-modal>\n</ng-template>\n\n<ng-template #modalContent>\n <div\n class=\"str-chat__message-bounce-prompt\"\n data-testid=\"message-bounce-prompt\"\n >\n <div class=\"str-chat__message-bounce-prompt-header\">\n {{\n \"streamChat.This message did not meet our content guidelines\"\n | translate\n }}\n </div>\n <div class=\"str-chat__message-bounce-actions\">\n <button\n class=\"str-chat__message-bounce-edit\"\n data-testid=\"message-bounce-edit\"\n (click)=\"editMessage()\"\n (keyup.enter)=\"editMessage()\"\n type=\"button\"\n >\n {{ \"streamChat.Edit Message\" | translate }}\n </button>\n <button\n class=\"str-chat__message-bounce-send\"\n data-testid=\"message-bounce-send\"\n (click)=\"resendMessage()\"\n (keyup.enter)=\"resendMessage()\"\n >\n {{ \"streamChat.Send Anyway\" | translate }}\n </button>\n <button\n class=\"str-chat__message-bounce-delete\"\n data-testid=\"message-bounce-delete\"\n (click)=\"deleteMessage()\"\n (keyup.enter)=\"deleteMessage()\"\n >\n {{ \"streamChat.Delete\" | translate }}\n </button>\n </div>\n </div>\n</ng-template>\n", components: [{ type: ModalComponent, selector: "stream-modal", inputs: ["isOpen", "content"], outputs: ["isOpenChange"] }], directives: [{ type: i5__namespace.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet"] }, { type: i5__namespace.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }], pipes: { "async": i5__namespace.AsyncPipe, "translate": i6__namespace.TranslatePipe } });
5253
+ i0__namespace.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0__namespace, type: MessageBouncePromptComponent, decorators: [{
5073
5254
  type: i0.Component,
5074
5255
  args: [{
5075
- selector: 'stream-message-actions-box',
5076
- templateUrl: './message-actions-box.component.html',
5256
+ selector: 'stream-message-bounce-prompt',
5257
+ templateUrl: './message-bounce-prompt.component.html',
5077
5258
  styles: [],
5078
5259
  }]
5079
- }], ctorParameters: function () { return [{ type: CustomTemplatesService }, { type: MessageActionsService }, { type: i0__namespace.ChangeDetectorRef }]; }, propDecorators: { isOpen: [{
5080
- type: i0.Input
5081
- }], isMine: [{
5082
- type: i0.Input
5083
- }], message: [{
5084
- type: i0.Input
5085
- }], enabledActions: [{
5086
- type: i0.Input
5087
- }], customActions: [{
5088
- type: i0.Input
5089
- }], displayedActionsCount: [{
5090
- type: i0.Output
5091
- }], isEditing: [{
5092
- type: i0.Output
5093
- }], modalContent: [{
5094
- type: i0.ViewChild,
5095
- args: ['modalContent', { static: true }]
5260
+ }], ctorParameters: function () { return [{ type: ChannelService }, { type: CustomTemplatesService }, { type: MessageActionsService }]; }, propDecorators: { class: [{
5261
+ type: i0.HostBinding
5096
5262
  }] } });
5097
5263
 
5098
5264
  /**
5099
5265
  * The `Channel` component is a container component that displays the [`ChannelHeader`](./ChannelHeaderComponent.mdx), [`MessageList`](./MessageListComponent.mdx), [`NotificationList`](./NotificationListComponent.mdx) and [`MessageInput`](./MessageInputComponent.mdx) components. You can also provide the [`Thread`](./ThreadComponent.mdx) component to use message [threads](https://getstream.io/chat/docs/javascript/threads/?language=javascript).
5100
5266
  */
5101
5267
  var ChannelComponent = /** @class */ (function () {
5102
- function ChannelComponent(channelService, themeService) {
5268
+ function ChannelComponent(channelService, themeService, customTemplatesService) {
5103
5269
  this.channelService = channelService;
5104
5270
  this.themeService = themeService;
5271
+ this.customTemplatesService = customTemplatesService;
5105
5272
  this.subscriptions = [];
5106
5273
  this.isError$ = rxjs.combineLatest([
5107
5274
  this.channelService.channelQueryState$,
@@ -5123,8 +5290,8 @@
5123
5290
  }
5124
5291
  return ChannelComponent;
5125
5292
  }());
5126
- ChannelComponent.ɵfac = i0__namespace.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0__namespace, type: ChannelComponent, deps: [{ token: ChannelService }, { token: ThemeService }], target: i0__namespace.ɵɵFactoryTarget.Component });
5127
- ChannelComponent.ɵcmp = i0__namespace.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.5", type: ChannelComponent, selector: "stream-channel", ngImport: i0__namespace, template: "<div\n class=\"str-chat str-chat-channel messaging str-chat__channel str-chat__theme-{{\n theme$ | async\n }}\"\n>\n <div\n class=\"str-chat__container\"\n *ngIf=\"\n (isError$ | async) === false &&\n (isInitializing$ | async) === false &&\n (isActiveChannel$ | async) === true;\n else noChannel\n \"\n >\n <div class=\"str-chat__main-panel\">\n <ng-content></ng-content>\n </div>\n <ng-content\n *ngIf=\"isActiveThread$ | async\"\n select='[name=\"thread\"]'\n ></ng-content>\n </div>\n <ng-template #noChannel>\n <div\n class=\"str-chat__empty-channel\"\n *ngIf=\"\n (isInitializing$ | async) === false &&\n ((isError$ | async) === true || (isActiveChannel$ | async) === false)\n \"\n >\n <stream-icon icon=\"chat-bubble\"></stream-icon>\n <p class=\"str-chat__empty-channel-text\">\n {{ \"streamChat.No chats here yet\u2026\" | translate }}\n </p>\n <div class=\"str-chat__empty-channel-notifications\">\n <stream-notification-list></stream-notification-list>\n </div>\n </div>\n <div\n *ngIf=\"\n (isInitializing$ | async) === true &&\n (isError$ | async) === false &&\n (isActiveChannel$ | async) === false\n \"\n class=\"str-chat__loading-channel\"\n >\n <div class=\"str-chat__loading-channel-header\">\n <div class=\"str-chat__loading-channel-header-avatar\"></div>\n <div class=\"str-chat__loading-channel-header-end\">\n <div class=\"str-chat__loading-channel-header-name\"></div>\n <div class=\"str-chat__loading-channel-header-info\"></div>\n </div>\n </div>\n <div class=\"str-chat__loading-channel-message-list\">\n <div class=\"str-chat__loading-channel-message\">\n <div class=\"str-chat__loading-channel-message-avatar\"></div>\n <div class=\"str-chat__loading-channel-message-end\">\n <div class=\"str-chat__loading-channel-message-sender\"></div>\n <div class=\"str-chat__loading-channel-message-last-row\">\n <div class=\"str-chat__loading-channel-message-text\"></div>\n <div class=\"str-chat__loading-channel-message-date\"></div>\n </div>\n </div>\n </div>\n <div class=\"str-chat__loading-channel-message\">\n <div class=\"str-chat__loading-channel-message-avatar\"></div>\n <div class=\"str-chat__loading-channel-message-end\">\n <div class=\"str-chat__loading-channel-message-sender\"></div>\n <div class=\"str-chat__loading-channel-message-last-row\">\n <div class=\"str-chat__loading-channel-message-text\"></div>\n <div class=\"str-chat__loading-channel-message-date\"></div>\n </div>\n </div>\n </div>\n <div class=\"str-chat__loading-channel-message\">\n <div class=\"str-chat__loading-channel-message-avatar\"></div>\n <div class=\"str-chat__loading-channel-message-end\">\n <div class=\"str-chat__loading-channel-message-sender\"></div>\n <div class=\"str-chat__loading-channel-message-last-row\">\n <div class=\"str-chat__loading-channel-message-text\"></div>\n <div class=\"str-chat__loading-channel-message-date\"></div>\n </div>\n </div>\n </div>\n </div>\n <div class=\"str-chat__loading-channel-message-input-row\">\n <div class=\"str-chat__loading-channel-message-input\"></div>\n <div class=\"str-chat__loading-channel-message-send\"></div>\n </div>\n </div>\n </ng-template>\n</div>\n", components: [{ type: IconComponent, selector: "stream-icon", inputs: ["icon", "size"] }, { type: NotificationListComponent, selector: "stream-notification-list" }], directives: [{ type: i5__namespace.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }], pipes: { "async": i5__namespace.AsyncPipe, "translate": i6__namespace.TranslatePipe } });
5293
+ ChannelComponent.ɵfac = i0__namespace.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0__namespace, type: ChannelComponent, deps: [{ token: ChannelService }, { token: ThemeService }, { token: CustomTemplatesService }], target: i0__namespace.ɵɵFactoryTarget.Component });
5294
+ ChannelComponent.ɵcmp = i0__namespace.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.5", type: ChannelComponent, selector: "stream-channel", ngImport: i0__namespace, template: "<div\n class=\"str-chat str-chat-channel messaging str-chat__channel str-chat__theme-{{\n theme$ | async\n }}\"\n>\n <div\n class=\"str-chat__container\"\n *ngIf=\"\n (isError$ | async) === false &&\n (isInitializing$ | async) === false &&\n (isActiveChannel$ | async) === true;\n else noChannel\n \"\n >\n <ng-container\n *ngTemplateOutlet=\"\n (customTemplatesService.editMessageFormTemplate$ | async) ||\n defaultEditMessageForm\n \"\n ></ng-container>\n <ng-template #defaultEditMessageForm>\n <stream-edit-message-form></stream-edit-message-form>\n </ng-template>\n <ng-container\n *ngTemplateOutlet=\"\n (customTemplatesService.messageBouncePromptTemplate$ | async) ||\n defaultMessageBouncePrompt\n \"\n ></ng-container>\n <ng-template #defaultMessageBouncePrompt>\n <stream-message-bounce-prompt></stream-message-bounce-prompt>\n </ng-template>\n <div class=\"str-chat__main-panel\">\n <ng-content></ng-content>\n </div>\n <ng-content\n *ngIf=\"isActiveThread$ | async\"\n select='[name=\"thread\"]'\n ></ng-content>\n </div>\n <ng-template #noChannel>\n <div\n class=\"str-chat__empty-channel\"\n *ngIf=\"\n (isInitializing$ | async) === false &&\n ((isError$ | async) === true || (isActiveChannel$ | async) === false)\n \"\n >\n <stream-icon icon=\"chat-bubble\"></stream-icon>\n <p class=\"str-chat__empty-channel-text\">\n {{ \"streamChat.No chats here yet\u2026\" | translate }}\n </p>\n <div class=\"str-chat__empty-channel-notifications\">\n <stream-notification-list></stream-notification-list>\n </div>\n </div>\n <div\n *ngIf=\"\n (isInitializing$ | async) === true &&\n (isError$ | async) === false &&\n (isActiveChannel$ | async) === false\n \"\n class=\"str-chat__loading-channel\"\n >\n <div class=\"str-chat__loading-channel-header\">\n <div class=\"str-chat__loading-channel-header-avatar\"></div>\n <div class=\"str-chat__loading-channel-header-end\">\n <div class=\"str-chat__loading-channel-header-name\"></div>\n <div class=\"str-chat__loading-channel-header-info\"></div>\n </div>\n </div>\n <div class=\"str-chat__loading-channel-message-list\">\n <div class=\"str-chat__loading-channel-message\">\n <div class=\"str-chat__loading-channel-message-avatar\"></div>\n <div class=\"str-chat__loading-channel-message-end\">\n <div class=\"str-chat__loading-channel-message-sender\"></div>\n <div class=\"str-chat__loading-channel-message-last-row\">\n <div class=\"str-chat__loading-channel-message-text\"></div>\n <div class=\"str-chat__loading-channel-message-date\"></div>\n </div>\n </div>\n </div>\n <div class=\"str-chat__loading-channel-message\">\n <div class=\"str-chat__loading-channel-message-avatar\"></div>\n <div class=\"str-chat__loading-channel-message-end\">\n <div class=\"str-chat__loading-channel-message-sender\"></div>\n <div class=\"str-chat__loading-channel-message-last-row\">\n <div class=\"str-chat__loading-channel-message-text\"></div>\n <div class=\"str-chat__loading-channel-message-date\"></div>\n </div>\n </div>\n </div>\n <div class=\"str-chat__loading-channel-message\">\n <div class=\"str-chat__loading-channel-message-avatar\"></div>\n <div class=\"str-chat__loading-channel-message-end\">\n <div class=\"str-chat__loading-channel-message-sender\"></div>\n <div class=\"str-chat__loading-channel-message-last-row\">\n <div class=\"str-chat__loading-channel-message-text\"></div>\n <div class=\"str-chat__loading-channel-message-date\"></div>\n </div>\n </div>\n </div>\n </div>\n <div class=\"str-chat__loading-channel-message-input-row\">\n <div class=\"str-chat__loading-channel-message-input\"></div>\n <div class=\"str-chat__loading-channel-message-send\"></div>\n </div>\n </div>\n </ng-template>\n</div>\n", components: [{ type: EditMessageFormComponent, selector: "stream-edit-message-form" }, { type: MessageBouncePromptComponent, selector: "stream-message-bounce-prompt" }, { type: IconComponent, selector: "stream-icon", inputs: ["icon", "size"] }, { type: NotificationListComponent, selector: "stream-notification-list" }], directives: [{ type: i5__namespace.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i5__namespace.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet"] }], pipes: { "async": i5__namespace.AsyncPipe, "translate": i6__namespace.TranslatePipe } });
5128
5295
  i0__namespace.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0__namespace, type: ChannelComponent, decorators: [{
5129
5296
  type: i0.Component,
5130
5297
  args: [{
@@ -5132,7 +5299,7 @@
5132
5299
  templateUrl: './channel.component.html',
5133
5300
  styles: [],
5134
5301
  }]
5135
- }], ctorParameters: function () { return [{ type: ChannelService }, { type: ThemeService }]; } });
5302
+ }], ctorParameters: function () { return [{ type: ChannelService }, { type: ThemeService }, { type: CustomTemplatesService }]; } });
5136
5303
 
5137
5304
  var listUsers = function (users) {
5138
5305
  var outStr = '';
@@ -6008,22 +6175,6 @@
6008
6175
  }
6009
6176
  }
6010
6177
  }));
6011
- this.subscriptions.push(this.messageActionsService.messageToEdit$.subscribe(function (m) {
6012
- var _a;
6013
- var isEditing = false;
6014
- if (m && m.id === ((_a = _this.message) === null || _a === void 0 ? void 0 : _a.id)) {
6015
- isEditing = true;
6016
- }
6017
- if (isEditing !== _this.isEditing) {
6018
- _this.isEditing = isEditing;
6019
- if (!_this.isEditing) {
6020
- _this.isActionBoxOpen = false;
6021
- }
6022
- if (_this.isViewInited) {
6023
- _this.cdRef.detectChanges();
6024
- }
6025
- }
6026
- }));
6027
6178
  };
6028
6179
  MessageComponent.prototype.ngOnChanges = function (changes) {
6029
6180
  var _a, _b, _c, _d, _e, _f, _g;
@@ -6122,9 +6273,6 @@
6122
6273
  }
6123
6274
  };
6124
6275
  MessageComponent.prototype.messageActionsBoxClicked = function (popperContent) {
6125
- if (this.isEditing) {
6126
- return;
6127
- }
6128
6276
  popperContent.hide();
6129
6277
  };
6130
6278
  MessageComponent.prototype.getAttachmentListContext = function () {
@@ -6168,6 +6316,17 @@
6168
6316
  ownReactions: ((_d = this.message) === null || _d === void 0 ? void 0 : _d.own_reactions) || [],
6169
6317
  };
6170
6318
  };
6319
+ MessageComponent.prototype.unsentMessageClicked = function () {
6320
+ var _a, _b, _c, _d;
6321
+ if (((_a = this.message) === null || _a === void 0 ? void 0 : _a.status) === 'failed' &&
6322
+ ((_b = this.message) === null || _b === void 0 ? void 0 : _b.errorStatusCode) !== 403) {
6323
+ this.resendMessage();
6324
+ }
6325
+ else if (((_c = this.message) === null || _c === void 0 ? void 0 : _c.type) === 'error' &&
6326
+ ((_d = this.message) === null || _d === void 0 ? void 0 : _d.moderation_details)) {
6327
+ this.openMessageBouncePrompt();
6328
+ }
6329
+ };
6171
6330
  MessageComponent.prototype.resendMessage = function () {
6172
6331
  void this.channelService.resendMessage(this.message);
6173
6332
  };
@@ -6197,10 +6356,6 @@
6197
6356
  // message action box changes UI bindings in parent, so we'll have to rerun change detection
6198
6357
  _this.cdRef.detectChanges();
6199
6358
  },
6200
- isEditingChangeHandler: function (isEditing) {
6201
- _this.isEditing = isEditing;
6202
- _this.isActionBoxOpen = !_this.isEditing;
6203
- },
6204
6359
  customActions: this.customActions || [],
6205
6360
  };
6206
6361
  };
@@ -6234,6 +6389,9 @@
6234
6389
  MessageComponent.prototype.displayOriginalMessage = function () {
6235
6390
  this.createMessageParts(false);
6236
6391
  };
6392
+ MessageComponent.prototype.openMessageBouncePrompt = function () {
6393
+ this.channelService.bouncedMessage$.next(this.message);
6394
+ };
6237
6395
  MessageComponent.prototype.createMessageParts = function (shouldTranslate) {
6238
6396
  var _this = this;
6239
6397
  if (shouldTranslate === void 0) { shouldTranslate = true; }
@@ -6327,7 +6485,7 @@
6327
6485
  return MessageComponent;
6328
6486
  }());
6329
6487
  MessageComponent.ɵfac = i0__namespace.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0__namespace, type: MessageComponent, deps: [{ token: ChatClientService }, { token: ChannelService }, { token: CustomTemplatesService }, { token: i0__namespace.ChangeDetectorRef }, { token: ThemeService }, { token: DateParserService }, { token: i0__namespace.NgZone }, { token: MessageService }, { token: MessageActionsService }], target: i0__namespace.ɵɵFactoryTarget.Component });
6330
- MessageComponent.ɵcmp = i0__namespace.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.5", type: MessageComponent, selector: "stream-message", inputs: { message: "message", enabledMessageActions: "enabledMessageActions", isLastSentMessage: "isLastSentMessage", mode: "mode", isHighlighted: "isHighlighted", customActions: "customActions" }, viewQueries: [{ propertyName: "container", first: true, predicate: ["container"], descendants: true }], usesOnChanges: true, ngImport: i0__namespace, template: "<div\n #container\n class=\"str-chat__message-simple str-chat__message str-chat__message--{{\n message?.type\n }} str-chat__message--{{ message?.status }} {{\n message?.text ? 'str-chat__message--has-text' : 'has-no-text'\n }}\"\n [class.str-chat__message--me]=\"isSentByCurrentUser\"\n [class.str-chat__message--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 \"\n data-testid=\"message-container\"\n>\n <ng-container *ngIf=\"!message?.deleted_at; else deletedMessage\">\n <ng-container *ngIf=\"message?.type !== 'system'; else systemMessage\">\n <ng-container *ngIf=\"themeVersion === '1'\">\n <ng-container *ngTemplateOutlet=\"messageStatus\"></ng-container>\n </ng-container>\n <stream-avatar-placeholder\n data-testid=\"avatar\"\n class=\"str-chat-angular__avatar-host str-chat__message-sender-avatar\"\n [imageUrl]=\"message?.user?.image\"\n [name]=\"message?.user?.name || message?.user?.id\"\n type=\"user\"\n location=\"message-sender\"\n [user]=\"message?.user || undefined\"\n ></stream-avatar-placeholder>\n <div class=\"str-chat__message-inner\">\n <div\n class=\"str-chat__message-simple__actions str-chat__message-options\"\n data-testid=\"message-options\"\n [class.str-chat__message-actions-open]=\"isActionBoxOpen\"\n [class.str-chat__message-edit-in-progress]=\"isEditing\"\n *ngIf=\"areOptionsVisible\"\n >\n <div\n data-testid=\"message-actions-container\"\n #messageActionsToggle\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 [class.str-chat-angular__message-simple__actions__action--options--editing]=\"\n isEditing\n \"\n [popper]=\"popperContent\"\n [popperTrigger]=\"popperTriggerClick\"\n [popperPlacement]=\"popperPlacementAuto\"\n [popperHideOnScroll]=\"false\"\n [popperHideOnClickOutside]=\"true\"\n [popperHideOnMouseLeave]=\"false\"\n [popperDisableAnimation]=\"true\"\n (popperOnHidden)=\"isActionBoxOpen = false\"\n >\n <popper-content #popperContent>\n <ng-template\n #defaultMessageActionsBox\n let-isOpen=\"isOpen\"\n let-isMine=\"isMine\"\n let-enabledActions=\"enabledActions\"\n let-messageInput=\"message\"\n let-customActions=\"customActions\"\n >\n <stream-message-actions-box\n (click)=\"messageActionsBoxClicked(popperContent)\"\n *ngIf=\"isOpen\"\n [isOpen]=\"isOpen\"\n [isMine]=\"isMine\"\n [enabledActions]=\"enabledActions\"\n [customActions]=\"customActions\"\n [message]=\"messageInput\"\n ></stream-message-actions-box>\n </ng-template>\n <ng-container\n *ngTemplateOutlet=\"\n (customTemplatesService.messageActionsBoxTemplate$ | async) ||\n defaultMessageActionsBox;\n context: getMessageActionsBoxContext()\n \"\n >\n </ng-container>\n </popper-content>\n <div\n class=\"str-chat__message-actions-box-button\"\n data-testid=\"action-icon\"\n (click)=\"messageActionsClicked()\"\n (keyup.enter)=\"messageActionsClicked()\"\n *ngIf=\"visibleMessageActionsCount > 0\"\n >\n <stream-icon-placeholder\n icon=\"action-icon\"\n class=\"str-chat__message-action-icon\"\n ></stream-icon-placeholder>\n </div>\n </div>\n <div\n *ngIf=\"\n enabledMessageActions.indexOf('send-reply') !== -1 &&\n mode === 'main'\n \"\n class=\"\n str-chat__message-simple__actions__action\n str-chat__message-simple__actions__action--thread\n str-chat__message-reply-in-thread-button\n \"\n data-testid=\"reply-in-thread\"\n (click)=\"setAsActiveParentMessage()\"\n (keyup.enter)=\"setAsActiveParentMessage()\"\n >\n <stream-icon-placeholder\n class=\"str-chat__message-action-icon\"\n icon=\"reply-in-thread\"\n ></stream-icon-placeholder>\n </div>\n <div\n *ngIf=\"canReactToMessage\"\n class=\"\n str-chat__message-simple__actions__action\n str-chat__message-simple__actions__action--reactions\n str-chat__message-reactions-button\n \"\n data-testid=\"reaction-icon\"\n (click)=\"isReactionSelectorOpen = !isReactionSelectorOpen\"\n (keyup.enter)=\"isReactionSelectorOpen = !isReactionSelectorOpen\"\n >\n <stream-icon-placeholder\n class=\"str-chat__message-action-icon\"\n icon=\"reaction-icon\"\n ></stream-icon-placeholder>\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-isSelectorOpen=\"isSelectorOpen\"\n let-isSelectorOpenChangeHandler=\"isSelectorOpenChangeHandler\"\n let-messageId=\"messageId\"\n let-ownReactions=\"ownReactions\"\n >\n <stream-message-reactions\n [messageReactionCounts]=\"messageReactionCounts\"\n [latestReactions]=\"latestReactions\"\n [isSelectorOpen]=\"isSelectorOpen\"\n (isSelectorOpenChange)=\"isSelectorOpenChangeHandler($event)\"\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 <!-- transform: translate3d(0, 0, 0) fixes scrolling issues on iOS, see: https://stackoverflow.com/questions/50105780/elements-disappear-when-scrolling-in-safari-webkit-transform-fix-only-works-t/50144295#50144295 -->\n <!-- transform: none is required when image carousel is open in order for the modal to be correctly positioned, see how the transform property changes the behavior of fixed positioned elements https://developer.mozilla.org/en-US/docs/Web/CSS/position -->\n <div\n class=\"str-chat__message-bubble\"\n style=\"transform: {{\n imageAttachmentModalState === 'opened'\n ? 'none'\n : 'translate3d(0, 0, 0)'\n }}\"\n >\n <ng-container *ngIf=\"hasAttachment && !message?.quoted_message\">\n <ng-container\n *ngTemplateOutlet=\"attachmentsTemplate\"\n ></ng-container>\n </ng-container>\n <div\n class=\"str-chat__message-text\"\n tabindex=\"0\"\n *ngIf=\"message?.text || (message?.quoted_message && hasAttachment)\"\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 (click)=\"\n message?.status === 'failed' && message?.errorStatusCode !== 403\n ? resendMessage()\n : undefined\n \"\n (keyup.enter)=\"\n message?.status === 'failed' && message?.errorStatusCode !== 403\n ? resendMessage()\n : undefined\n \"\n >\n <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 data-testid=\"client-error-message\"\n *ngIf=\"message?.type === 'error'\"\n class=\"\n str-chat__simple-message--error-message\n str-chat__message--error-message\n \"\n >\n {{ \"streamChat.Error \u00B7 Unsent\" | translate }}\n </div>\n <div\n data-testid=\"error-message\"\n *ngIf=\"message?.status === 'failed'\"\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 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 *ngIf=\"themeVersion === '2'\"\n class=\"str-chat__message-error-icon\"\n icon=\"error\"\n ></stream-icon-placeholder>\n </div>\n <ng-container\n *ngTemplateOutlet=\"\n replyCountButton;\n context: { position: 'inside-message-bubble' }\n \"\n ></ng-container>\n <ng-container\n *ngTemplateOutlet=\"\n messageDateAndSender;\n context: { position: 'inside-message-bubble' }\n \"\n ></ng-container>\n </div>\n <ng-container\n *ngTemplateOutlet=\"\n replyCountButton;\n context: { position: 'outside-message-bubble', message: message }\n \"\n ></ng-container>\n\n <ng-container\n *ngTemplateOutlet=\"\n messageDateAndSender;\n context: { position: 'outside-message-bubble' }\n \"\n ></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 [imageUrl]=\"message?.quoted_message?.user?.image\"\n [name]=\"\n message?.quoted_message?.user?.name || message?.quoted_message?.user?.id\n \"\n [size]=\"20\"\n type=\"user\"\n location=\"quoted-message-sender\"\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<!-- We need these markups in slightly different positions in theme-v1 and theme-v2, this soultion makes that possible without duplicating the code -->\n<ng-template #messageDateAndSender let-position=\"position\">\n <ng-container\n *ngIf=\"\n (position === 'inside-message-bubble' && themeVersion === '1') ||\n (position === 'outside-message-bubble' && themeVersion === '2')\n \"\n >\n <div\n class=\"str-chat__translation-notice\"\n *ngIf=\"shouldDisplayTranslationNotice\"\n data-testid=\"translation-notice\"\n >\n <button\n data-testid=\"see-original\"\n *ngIf=\"displayedMessageTextContent === 'translation'\"\n (click)=\"displayOriginalMessage()\"\n (keyup.enter)=\"displayOriginalMessage()\"\n translate\n >\n streamChat.See original (automatically translated)\n </button>\n <button\n data-testid=\"see-translation\"\n *ngIf=\"displayedMessageTextContent === 'original'\"\n (click)=\"displayTranslatedMessage()\"\n (keyup.enter)=\"displayTranslatedMessage()\"\n translate\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 *ngIf=\"themeVersion === '2'\">\n <ng-container *ngTemplateOutlet=\"messageStatus\"></ng-container>\n </ng-container>\n <span\n data-testid=\"sender\"\n *ngIf=\"!isSentByCurrentUser\"\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 data-testid=\"date\" class=\"str-chat__message-simple-timestamp\">\n {{ parsedDate }}\n </span>\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 [popper]=\"popperContent\"\n [popperTrigger]=\"popperTriggerHover\"\n [popperPlacement]=\"popperPlacementAuto\"\n [popperHideOnScroll]=\"false\"\n [popperHideOnClickOutside]=\"false\"\n (hover)=\"$event.stopPropagation()\"\n >\n <popper-content #popperContent>\n <div class=\"str-chat__tooltip str-chat__tooltip-angular\">\n {{ \"streamChat.Delivered\" | translate }}\n </div>\n </popper-content>\n <stream-icon-placeholder\n data-testid=\"delivered-icon\"\n icon=\"delivered-icon\"\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 [popper]=\"popperContent\"\n [popperTrigger]=\"popperTriggerHover\"\n [popperPlacement]=\"popperPlacementAuto\"\n [popperHideOnScroll]=\"false\"\n [popperHideOnClickOutside]=\"false\"\n (hover)=\"$event.stopPropagation()\"\n >\n <popper-content #popperContent>\n <div class=\"str-chat__tooltip str-chat__tooltip-angular\">\n {{ \"streamChat.Sending...\" | translate }}\n </div>\n </popper-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>\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 [popper]=\"popperContent\"\n [popperTrigger]=\"popperTriggerHover\"\n [popperPlacement]=\"popperPlacementAuto\"\n [popperHideOnScroll]=\"false\"\n [popperHideOnClickOutside]=\"false\"\n (hover)=\"$event.stopPropagation()\"\n >\n <popper-content #popperContent>\n <div\n class=\"str-chat__tooltip str-chat__tooltip-angular\"\n data-testid=\"read-by-tooltip\"\n >\n {{ readByText }}\n </div>\n </popper-content>\n <stream-avatar-placeholder\n class=\"str-chat-angular__avatar-host\"\n data-test-id=\"last-read-user-avatar\"\n [size]=\"15\"\n [imageUrl]=\"lastReadUser?.image\"\n [name]=\"lastReadUser?.name || lastReadUser?.id\"\n type=\"user\"\n location=\"message-reader\"\n [user]=\"lastReadUser\"\n ></stream-avatar-placeholder>\n <span\n data-test-id=\"read-by-length\"\n *ngIf=\"isReadByMultipleUsers\"\n class=\"str-chat__message-simple-status-number\"\n >\n {{ (message?.readBy)!.length }}\n </span>\n </span>\n </ng-template>\n </ng-container>\n</ng-template>\n\n<ng-template #replyCountButton let-position=\"position\">\n <div\n *ngIf=\"\n (position === 'inside-message-bubble' && themeVersion === '1') ||\n (position === 'outside-message-bubble' && themeVersion === '2')\n \"\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 <stream-icon-placeholder\n *ngIf=\"themeVersion === '1'\"\n stream-icon-placeholder\n icon=\"reply\"\n ></stream-icon-placeholder>\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", components: [{ type: AvatarPlaceholderComponent, selector: "stream-avatar-placeholder", inputs: ["name", "imageUrl", "size", "location", "channel", "user", "type", "initialsType", "showOnlineIndicator"] }, { type: i9__namespace.NgxPopperjsContentComponent, selector: "popper-content", exportAs: ["ngxPopperjsContent"] }, { type: MessageActionsBoxComponent, selector: "stream-message-actions-box", inputs: ["isOpen", "isMine", "message", "enabledActions", "customActions"], outputs: ["displayedActionsCount", "isEditing"] }, { type: IconPlaceholderComponent, selector: "stream-icon-placeholder", inputs: ["icon", "size"] }, { type: MessageReactionsComponent, selector: "stream-message-reactions", inputs: ["messageId", "messageReactionCounts", "isSelectorOpen", "latestReactions", "ownReactions"], outputs: ["isSelectorOpenChange"] }, { type: AttachmentListComponent, selector: "stream-attachment-list", inputs: ["messageId", "parentMessageId", "attachments"], outputs: ["imageModalStateChange"] }, { type: LoadingIndicatorPlaceholderComponent, selector: "stream-loading-indicator-placeholder", inputs: ["size", "color"] }], directives: [{ type: i5__namespace.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i5__namespace.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet"] }, { type: i9__namespace.NgxPopperjsDirective, selector: "[popper]", inputs: ["popperTimeout", "popperTimeoutAfterShow", "popperApplyClass", "popper", "popperDisabled", "popperPlacement", "popperApplyArrowClass", "popperPreventOverflow", "popperHideOnClickOutside", "popperTrigger", "popperStyles", "popperAriaDescribeBy", "popperAriaRole", "popperBoundaries", "popperCloseOnClickOutside", "popperDisableAnimation", "popperDisableStyle", "popperHideOnMouseLeave", "popperHideOnScroll", "popperAppendTo", "popperModifiers", "popperPositionFixed", "popperDelay", "popperShowOnStart", "popperTarget"], outputs: ["popperOnHidden", "popperOnShown", "popperOnUpdate"], exportAs: ["popper"] }, { type: i5__namespace.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i6__namespace.TranslateDirective, selector: "[translate],[ngx-translate]", inputs: ["translate", "translateParams"] }], pipes: { "async": i5__namespace.AsyncPipe, "translate": i6__namespace.TranslatePipe }, changeDetection: i0__namespace.ChangeDetectionStrategy.OnPush });
6488
+ MessageComponent.ɵcmp = i0__namespace.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.5", type: MessageComponent, selector: "stream-message", inputs: { message: "message", enabledMessageActions: "enabledMessageActions", isLastSentMessage: "isLastSentMessage", mode: "mode", isHighlighted: "isHighlighted", customActions: "customActions" }, viewQueries: [{ propertyName: "container", first: true, predicate: ["container"], descendants: true }], usesOnChanges: true, ngImport: i0__namespace, template: "<div\n #container\n class=\"str-chat__message-simple str-chat__message str-chat__message--{{\n message?.type\n }} str-chat__message--{{ message?.status }} {{\n message?.text ? 'str-chat__message--has-text' : 'has-no-text'\n }}\"\n [class.str-chat__message--me]=\"isSentByCurrentUser\"\n [class.str-chat__message--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 data-testid=\"message-container\"\n>\n <ng-container *ngIf=\"!message?.deleted_at; else deletedMessage\">\n <ng-container *ngIf=\"message?.type !== 'system'; else systemMessage\">\n <ng-container *ngIf=\"themeVersion === '1'\">\n <ng-container *ngTemplateOutlet=\"messageStatus\"></ng-container>\n </ng-container>\n <stream-avatar-placeholder\n data-testid=\"avatar\"\n class=\"str-chat-angular__avatar-host str-chat__message-sender-avatar\"\n [imageUrl]=\"message?.user?.image\"\n [name]=\"message?.user?.name || message?.user?.id\"\n type=\"user\"\n location=\"message-sender\"\n [user]=\"message?.user || undefined\"\n ></stream-avatar-placeholder>\n <div class=\"str-chat__message-inner\">\n <div\n class=\"str-chat__message-simple__actions str-chat__message-options\"\n data-testid=\"message-options\"\n [class.str-chat__message-actions-open]=\"isActionBoxOpen\"\n *ngIf=\"areOptionsVisible\"\n >\n <div\n data-testid=\"message-actions-container\"\n #messageActionsToggle\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 [popper]=\"popperContent\"\n [popperTrigger]=\"popperTriggerClick\"\n [popperPlacement]=\"popperPlacementAuto\"\n [popperHideOnScroll]=\"false\"\n [popperHideOnClickOutside]=\"true\"\n [popperHideOnMouseLeave]=\"false\"\n [popperDisableAnimation]=\"true\"\n (popperOnHidden)=\"isActionBoxOpen = false\"\n >\n <popper-content #popperContent>\n <ng-template\n #defaultMessageActionsBox\n let-isOpen=\"isOpen\"\n let-isMine=\"isMine\"\n let-enabledActions=\"enabledActions\"\n let-messageInput=\"message\"\n let-customActions=\"customActions\"\n >\n <stream-message-actions-box\n (click)=\"messageActionsBoxClicked(popperContent)\"\n *ngIf=\"isOpen\"\n [isOpen]=\"isOpen\"\n [isMine]=\"isMine\"\n [enabledActions]=\"enabledActions\"\n [customActions]=\"customActions\"\n [message]=\"messageInput\"\n ></stream-message-actions-box>\n </ng-template>\n <ng-container\n *ngTemplateOutlet=\"\n (customTemplatesService.messageActionsBoxTemplate$ | async) ||\n defaultMessageActionsBox;\n context: getMessageActionsBoxContext()\n \"\n >\n </ng-container>\n </popper-content>\n <div\n class=\"str-chat__message-actions-box-button\"\n data-testid=\"action-icon\"\n (click)=\"messageActionsClicked()\"\n (keyup.enter)=\"messageActionsClicked()\"\n *ngIf=\"visibleMessageActionsCount > 0\"\n >\n <stream-icon-placeholder\n icon=\"action-icon\"\n class=\"str-chat__message-action-icon\"\n ></stream-icon-placeholder>\n </div>\n </div>\n <div\n *ngIf=\"\n enabledMessageActions.indexOf('send-reply') !== -1 &&\n mode === 'main'\n \"\n class=\"\n str-chat__message-simple__actions__action\n str-chat__message-simple__actions__action--thread\n str-chat__message-reply-in-thread-button\n \"\n data-testid=\"reply-in-thread\"\n (click)=\"setAsActiveParentMessage()\"\n (keyup.enter)=\"setAsActiveParentMessage()\"\n >\n <stream-icon-placeholder\n class=\"str-chat__message-action-icon\"\n icon=\"reply-in-thread\"\n ></stream-icon-placeholder>\n </div>\n <div\n *ngIf=\"canReactToMessage\"\n class=\"\n str-chat__message-simple__actions__action\n str-chat__message-simple__actions__action--reactions\n str-chat__message-reactions-button\n \"\n data-testid=\"reaction-icon\"\n (click)=\"isReactionSelectorOpen = !isReactionSelectorOpen\"\n (keyup.enter)=\"isReactionSelectorOpen = !isReactionSelectorOpen\"\n >\n <stream-icon-placeholder\n class=\"str-chat__message-action-icon\"\n icon=\"reaction-icon\"\n ></stream-icon-placeholder>\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-isSelectorOpen=\"isSelectorOpen\"\n let-isSelectorOpenChangeHandler=\"isSelectorOpenChangeHandler\"\n let-messageId=\"messageId\"\n let-ownReactions=\"ownReactions\"\n >\n <stream-message-reactions\n [messageReactionCounts]=\"messageReactionCounts\"\n [latestReactions]=\"latestReactions\"\n [isSelectorOpen]=\"isSelectorOpen\"\n (isSelectorOpenChange)=\"isSelectorOpenChangeHandler($event)\"\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 <!-- transform: translate3d(0, 0, 0) fixes scrolling issues on iOS, see: https://stackoverflow.com/questions/50105780/elements-disappear-when-scrolling-in-safari-webkit-transform-fix-only-works-t/50144295#50144295 -->\n <!-- transform: none is required when image carousel is open in order for the modal to be correctly positioned, see how the transform property changes the behavior of fixed positioned elements https://developer.mozilla.org/en-US/docs/Web/CSS/position -->\n <div\n class=\"str-chat__message-bubble\"\n style=\"transform: {{\n imageAttachmentModalState === 'opened'\n ? 'none'\n : 'translate3d(0, 0, 0)'\n }}\"\n >\n <ng-container *ngIf=\"hasAttachment && !message?.quoted_message\">\n <ng-container\n *ngTemplateOutlet=\"attachmentsTemplate\"\n ></ng-container>\n </ng-container>\n <div\n class=\"str-chat__message-text\"\n tabindex=\"0\"\n *ngIf=\"message?.text || (message?.quoted_message && hasAttachment)\"\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 (click)=\"unsentMessageClicked()\"\n (keyup.enter)=\"unsentMessageClicked()\"\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 data-testid=\"client-error-message\"\n *ngIf=\"message?.type === 'error'\"\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 data-testid=\"error-message\"\n *ngIf=\"message?.status === 'failed'\"\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 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 *ngIf=\"themeVersion === '2'\"\n class=\"str-chat__message-error-icon\"\n icon=\"error\"\n ></stream-icon-placeholder>\n </div>\n <ng-container\n *ngTemplateOutlet=\"\n replyCountButton;\n context: { position: 'inside-message-bubble' }\n \"\n ></ng-container>\n <ng-container\n *ngTemplateOutlet=\"\n messageDateAndSender;\n context: { position: 'inside-message-bubble' }\n \"\n ></ng-container>\n </div>\n <ng-container\n *ngTemplateOutlet=\"\n replyCountButton;\n context: { position: 'outside-message-bubble', message: message }\n \"\n ></ng-container>\n\n <ng-container\n *ngTemplateOutlet=\"\n messageDateAndSender;\n context: { position: 'outside-message-bubble' }\n \"\n ></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 [imageUrl]=\"message?.quoted_message?.user?.image\"\n [name]=\"\n message?.quoted_message?.user?.name || message?.quoted_message?.user?.id\n \"\n [size]=\"20\"\n type=\"user\"\n location=\"quoted-message-sender\"\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<!-- We need these markups in slightly different positions in theme-v1 and theme-v2, this soultion makes that possible without duplicating the code -->\n<ng-template #messageDateAndSender let-position=\"position\">\n <ng-container\n *ngIf=\"\n (position === 'inside-message-bubble' && themeVersion === '1') ||\n (position === 'outside-message-bubble' && themeVersion === '2')\n \"\n >\n <div\n class=\"str-chat__translation-notice\"\n *ngIf=\"shouldDisplayTranslationNotice\"\n data-testid=\"translation-notice\"\n >\n <button\n data-testid=\"see-original\"\n *ngIf=\"displayedMessageTextContent === 'translation'\"\n (click)=\"displayOriginalMessage()\"\n (keyup.enter)=\"displayOriginalMessage()\"\n translate\n >\n streamChat.See original (automatically translated)\n </button>\n <button\n data-testid=\"see-translation\"\n *ngIf=\"displayedMessageTextContent === 'original'\"\n (click)=\"displayTranslatedMessage()\"\n (keyup.enter)=\"displayTranslatedMessage()\"\n translate\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 *ngIf=\"themeVersion === '2'\">\n <ng-container *ngTemplateOutlet=\"messageStatus\"></ng-container>\n </ng-container>\n <span\n data-testid=\"sender\"\n *ngIf=\"!isSentByCurrentUser\"\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 data-testid=\"date\" class=\"str-chat__message-simple-timestamp\">\n {{ parsedDate }}\n </span>\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 [popper]=\"popperContent\"\n [popperTrigger]=\"popperTriggerHover\"\n [popperPlacement]=\"popperPlacementAuto\"\n [popperHideOnScroll]=\"false\"\n [popperHideOnClickOutside]=\"false\"\n (hover)=\"$event.stopPropagation()\"\n >\n <popper-content #popperContent>\n <div class=\"str-chat__tooltip str-chat__tooltip-angular\">\n {{ \"streamChat.Delivered\" | translate }}\n </div>\n </popper-content>\n <stream-icon-placeholder\n data-testid=\"delivered-icon\"\n icon=\"delivered-icon\"\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 [popper]=\"popperContent\"\n [popperTrigger]=\"popperTriggerHover\"\n [popperPlacement]=\"popperPlacementAuto\"\n [popperHideOnScroll]=\"false\"\n [popperHideOnClickOutside]=\"false\"\n (hover)=\"$event.stopPropagation()\"\n >\n <popper-content #popperContent>\n <div class=\"str-chat__tooltip str-chat__tooltip-angular\">\n {{ \"streamChat.Sending...\" | translate }}\n </div>\n </popper-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>\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 [popper]=\"popperContent\"\n [popperTrigger]=\"popperTriggerHover\"\n [popperPlacement]=\"popperPlacementAuto\"\n [popperHideOnScroll]=\"false\"\n [popperHideOnClickOutside]=\"false\"\n (hover)=\"$event.stopPropagation()\"\n >\n <popper-content #popperContent>\n <div\n class=\"str-chat__tooltip str-chat__tooltip-angular\"\n data-testid=\"read-by-tooltip\"\n >\n {{ readByText }}\n </div>\n </popper-content>\n <stream-avatar-placeholder\n class=\"str-chat-angular__avatar-host\"\n data-test-id=\"last-read-user-avatar\"\n [size]=\"15\"\n [imageUrl]=\"lastReadUser?.image\"\n [name]=\"lastReadUser?.name || lastReadUser?.id\"\n type=\"user\"\n location=\"message-reader\"\n [user]=\"lastReadUser\"\n ></stream-avatar-placeholder>\n <span\n data-test-id=\"read-by-length\"\n *ngIf=\"isReadByMultipleUsers\"\n class=\"str-chat__message-simple-status-number\"\n >\n {{ (message?.readBy)!.length }}\n </span>\n </span>\n </ng-template>\n </ng-container>\n</ng-template>\n\n<ng-template #replyCountButton let-position=\"position\">\n <div\n *ngIf=\"\n (position === 'inside-message-bubble' && themeVersion === '1') ||\n (position === 'outside-message-bubble' && themeVersion === '2')\n \"\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 <stream-icon-placeholder\n *ngIf=\"themeVersion === '1'\"\n stream-icon-placeholder\n icon=\"reply\"\n ></stream-icon-placeholder>\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", components: [{ type: AvatarPlaceholderComponent, selector: "stream-avatar-placeholder", inputs: ["name", "imageUrl", "size", "location", "channel", "user", "type", "initialsType", "showOnlineIndicator"] }, { type: i9__namespace.NgxPopperjsContentComponent, selector: "popper-content", exportAs: ["ngxPopperjsContent"] }, { type: MessageActionsBoxComponent, selector: "stream-message-actions-box", inputs: ["isOpen", "isMine", "message", "enabledActions", "customActions"], outputs: ["displayedActionsCount", "isEditing"] }, { type: IconPlaceholderComponent, selector: "stream-icon-placeholder", inputs: ["icon", "size"] }, { type: MessageReactionsComponent, selector: "stream-message-reactions", inputs: ["messageId", "messageReactionCounts", "isSelectorOpen", "latestReactions", "ownReactions"], outputs: ["isSelectorOpenChange"] }, { type: AttachmentListComponent, selector: "stream-attachment-list", inputs: ["messageId", "parentMessageId", "attachments"], outputs: ["imageModalStateChange"] }, { type: LoadingIndicatorPlaceholderComponent, selector: "stream-loading-indicator-placeholder", inputs: ["size", "color"] }], directives: [{ type: i5__namespace.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i5__namespace.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet"] }, { type: i9__namespace.NgxPopperjsDirective, selector: "[popper]", inputs: ["popperTimeout", "popperTimeoutAfterShow", "popperApplyClass", "popper", "popperDisabled", "popperPlacement", "popperApplyArrowClass", "popperPreventOverflow", "popperHideOnClickOutside", "popperTrigger", "popperStyles", "popperAriaDescribeBy", "popperAriaRole", "popperBoundaries", "popperCloseOnClickOutside", "popperDisableAnimation", "popperDisableStyle", "popperHideOnMouseLeave", "popperHideOnScroll", "popperAppendTo", "popperModifiers", "popperPositionFixed", "popperDelay", "popperShowOnStart", "popperTarget"], outputs: ["popperOnHidden", "popperOnShown", "popperOnUpdate"], exportAs: ["popper"] }, { type: i5__namespace.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i6__namespace.TranslateDirective, selector: "[translate],[ngx-translate]", inputs: ["translate", "translateParams"] }], pipes: { "async": i5__namespace.AsyncPipe, "translate": i6__namespace.TranslatePipe }, changeDetection: i0__namespace.ChangeDetectionStrategy.OnPush });
6331
6489
  i0__namespace.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0__namespace, type: MessageComponent, decorators: [{
6332
6490
  type: i0.Component,
6333
6491
  args: [{
@@ -7340,8 +7498,8 @@
7340
7498
  (_d = (_c = _this.chatClientService.chatClient) === null || _c === void 0 ? void 0 : _c.logger) === null || _d === void 0 ? void 0 : _d.call(_c, 'info', "Received one or more messages", {
7341
7499
  tags: "message list " + _this.mode,
7342
7500
  });
7343
- var currentLatestMessage = messages[messages.length - 1];
7344
- _this.newMessageReceived(currentLatestMessage);
7501
+ var currentLatestMessageInState = messages[messages.length - 1];
7502
+ _this.newMessageReceived(currentLatestMessageInState);
7345
7503
  var currentOldestMessage = messages[0];
7346
7504
  if (!_this.oldestMessage ||
7347
7505
  !messages.find(function (m) { return m.id === _this.oldestMessage.id; })) {
@@ -7373,7 +7531,8 @@
7373
7531
  _this.isLatestMessageInList =
7374
7532
  !_this.latestMessage ||
7375
7533
  messages.length === 0 ||
7376
- messages[messages.length - 1].id === _this.latestMessage.id;
7534
+ messages[messages.length - 1].id === _this.latestMessage.id ||
7535
+ _this.mode === 'thread';
7377
7536
  if (!_this.isLatestMessageInList) {
7378
7537
  _this.isUserScrolled = true;
7379
7538
  }
@@ -7438,15 +7597,20 @@
7438
7597
  }
7439
7598
  };
7440
7599
  MessageListComponent.prototype.newMessageReceived = function (message) {
7441
- var _a, _b, _c, _d, _e, _f;
7600
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j;
7601
+ var latestMessages = (_b = (_a = this.channelService.activeChannel) === null || _a === void 0 ? void 0 : _a.state) === null || _b === void 0 ? void 0 : _b.latestMessages;
7442
7602
  if (!this.latestMessage ||
7443
- ((_a = this.latestMessage.created_at) === null || _a === void 0 ? void 0 : _a.getTime()) < message.created_at.getTime()) {
7444
- (_c = (_b = this.chatClientService.chatClient) === null || _b === void 0 ? void 0 : _b.logger) === null || _c === void 0 ? void 0 : _c.call(_b, 'info', "Received new message", { tags: "message list " + this.mode });
7603
+ ((_c = this.latestMessage.created_at) === null || _c === void 0 ? void 0 : _c.getTime()) < message.created_at.getTime() ||
7604
+ (this.mode === 'main' &&
7605
+ latestMessages &&
7606
+ this.latestMessage &&
7607
+ ((_d = latestMessages[latestMessages.length - 1]) === null || _d === void 0 ? void 0 : _d.id) !== this.latestMessage.id)) {
7608
+ (_f = (_e = this.chatClientService.chatClient) === null || _e === void 0 ? void 0 : _e.logger) === null || _f === void 0 ? void 0 : _f.call(_e, 'info', "Received new message", { tags: "message list " + this.mode });
7445
7609
  var isNewChannel = !this.latestMessage;
7446
7610
  this.latestMessage = message;
7447
7611
  this.hasNewMessages = true;
7448
7612
  this.isNewMessageSentByUser =
7449
- ((_d = message.user) === null || _d === void 0 ? void 0 : _d.id) === ((_f = (_e = this.chatClientService.chatClient) === null || _e === void 0 ? void 0 : _e.user) === null || _f === void 0 ? void 0 : _f.id);
7613
+ ((_g = message.user) === null || _g === void 0 ? void 0 : _g.id) === ((_j = (_h = this.chatClientService.chatClient) === null || _h === void 0 ? void 0 : _h.user) === null || _j === void 0 ? void 0 : _j.id);
7450
7614
  if (this.isUserScrolled) {
7451
7615
  this.newMessageCountWhileBeingScrolled++;
7452
7616
  }
@@ -7632,7 +7796,9 @@
7632
7796
  TextareaDirective,
7633
7797
  ThreadComponent,
7634
7798
  IconPlaceholderComponent,
7635
- LoadingIndicatorPlaceholderComponent], imports: [i5.CommonModule,
7799
+ LoadingIndicatorPlaceholderComponent,
7800
+ EditMessageFormComponent,
7801
+ MessageBouncePromptComponent], imports: [i5.CommonModule,
7636
7802
  i6.TranslateModule,
7637
7803
  StreamAvatarModule,
7638
7804
  i9.NgxPopperjsModule], exports: [ChannelComponent,
@@ -7654,7 +7820,9 @@
7654
7820
  StreamAvatarModule,
7655
7821
  ThreadComponent,
7656
7822
  IconPlaceholderComponent,
7657
- LoadingIndicatorPlaceholderComponent] });
7823
+ LoadingIndicatorPlaceholderComponent,
7824
+ EditMessageFormComponent,
7825
+ MessageBouncePromptComponent] });
7658
7826
  StreamChatModule.ɵinj = i0__namespace.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0__namespace, type: StreamChatModule, imports: [[
7659
7827
  i5.CommonModule,
7660
7828
  i6.TranslateModule,
@@ -7685,6 +7853,8 @@
7685
7853
  ThreadComponent,
7686
7854
  IconPlaceholderComponent,
7687
7855
  LoadingIndicatorPlaceholderComponent,
7856
+ EditMessageFormComponent,
7857
+ MessageBouncePromptComponent,
7688
7858
  ],
7689
7859
  imports: [
7690
7860
  i5.CommonModule,
@@ -7713,6 +7883,8 @@
7713
7883
  ThreadComponent,
7714
7884
  IconPlaceholderComponent,
7715
7885
  LoadingIndicatorPlaceholderComponent,
7886
+ EditMessageFormComponent,
7887
+ MessageBouncePromptComponent,
7716
7888
  ],
7717
7889
  }]
7718
7890
  }] });
@@ -7797,6 +7969,7 @@
7797
7969
  exports.ChatClientService = ChatClientService;
7798
7970
  exports.CustomTemplatesService = CustomTemplatesService;
7799
7971
  exports.DateParserService = DateParserService;
7972
+ exports.EditMessageFormComponent = EditMessageFormComponent;
7800
7973
  exports.EmojiInputService = EmojiInputService;
7801
7974
  exports.IconComponent = IconComponent;
7802
7975
  exports.IconPlaceholderComponent = IconPlaceholderComponent;
@@ -7805,6 +7978,7 @@
7805
7978
  exports.LoadingIndicatorPlaceholderComponent = LoadingIndicatorPlaceholderComponent;
7806
7979
  exports.MessageActionsBoxComponent = MessageActionsBoxComponent;
7807
7980
  exports.MessageActionsService = MessageActionsService;
7981
+ exports.MessageBouncePromptComponent = MessageBouncePromptComponent;
7808
7982
  exports.MessageComponent = MessageComponent;
7809
7983
  exports.MessageInputComponent = MessageInputComponent;
7810
7984
  exports.MessageInputConfigService = MessageInputConfigService;