stream-chat-angular 2.1.0 → 2.4.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.
- package/README.md +1 -1
- package/assets/i18n/en.d.ts +2 -0
- package/assets/version.d.ts +1 -1
- package/bundles/stream-chat-angular.umd.js +115 -36
- package/bundles/stream-chat-angular.umd.js.map +1 -1
- package/esm2015/assets/i18n/en.js +3 -1
- package/esm2015/assets/version.js +2 -2
- package/esm2015/lib/channel-header/channel-header.component.js +12 -3
- package/esm2015/lib/channel-preview/channel-preview.component.js +9 -5
- package/esm2015/lib/channel.service.js +18 -5
- package/esm2015/lib/message/message.component.js +8 -4
- package/esm2015/lib/message-actions-box/message-actions-box.component.js +9 -7
- package/esm2015/lib/message-input/message-input.component.js +41 -18
- package/esm2015/lib/message-input/textarea.directive.js +12 -2
- package/esm2015/lib/message-list/message-list.component.js +5 -2
- package/fesm2015/stream-chat-angular.js +106 -36
- package/fesm2015/stream-chat-angular.js.map +1 -1
- package/lib/channel-header/channel-header.component.d.ts +1 -0
- package/lib/channel-preview/channel-preview.component.d.ts +1 -0
- package/lib/channel.service.d.ts +1 -0
- package/lib/message/message.component.d.ts +4 -1
- package/lib/message-actions-box/message-actions-box.component.d.ts +4 -3
- package/lib/message-input/message-input.component.d.ts +10 -4
- package/lib/message-input/textarea.directive.d.ts +1 -0
- package/lib/message-list/message-list.component.d.ts +3 -1
- package/package.json +11 -2
- package/src/assets/i18n/en.ts +4 -0
- package/src/assets/version.ts +1 -1
|
@@ -16,7 +16,7 @@ import transliterate from '@stream-io/transliterate';
|
|
|
16
16
|
import * as i5 from 'angular-mentions';
|
|
17
17
|
import { MentionModule } from 'angular-mentions';
|
|
18
18
|
|
|
19
|
-
const version = '2.
|
|
19
|
+
const version = '2.4.0';
|
|
20
20
|
|
|
21
21
|
class NotificationService {
|
|
22
22
|
constructor() {
|
|
@@ -218,7 +218,9 @@ class ChannelService {
|
|
|
218
218
|
channel.state.messages.forEach((m) => {
|
|
219
219
|
m.readBy = getReadBy(m, channel);
|
|
220
220
|
});
|
|
221
|
-
|
|
221
|
+
if (this.canSendReadEvents) {
|
|
222
|
+
void channel.markRead();
|
|
223
|
+
}
|
|
222
224
|
this.activeChannelMessagesSubject.next([...channel.state.messages]);
|
|
223
225
|
}
|
|
224
226
|
loadMoreMessages() {
|
|
@@ -457,9 +459,11 @@ class ChannelService {
|
|
|
457
459
|
this.activeChannelSubscriptions.push(channel.on('message.new', () => {
|
|
458
460
|
this.ngZone.run(() => {
|
|
459
461
|
this.activeChannelMessagesSubject.next([...channel.state.messages]);
|
|
460
|
-
this.activeChannel
|
|
461
|
-
.
|
|
462
|
-
|
|
462
|
+
this.activeChannel$.pipe(first()).subscribe((c) => {
|
|
463
|
+
if (this.canSendReadEvents) {
|
|
464
|
+
void (c === null || c === void 0 ? void 0 : c.markRead());
|
|
465
|
+
}
|
|
466
|
+
});
|
|
463
467
|
});
|
|
464
468
|
}));
|
|
465
469
|
this.activeChannelSubscriptions.push(channel.on('message.updated', (event) => this.messageUpdated(event)));
|
|
@@ -658,6 +662,15 @@ class ChannelService {
|
|
|
658
662
|
get channels() {
|
|
659
663
|
return this.channelsSubject.getValue() || [];
|
|
660
664
|
}
|
|
665
|
+
get canSendReadEvents() {
|
|
666
|
+
var _a;
|
|
667
|
+
const channel = this.activeChannelSubject.getValue();
|
|
668
|
+
if (!channel) {
|
|
669
|
+
return false;
|
|
670
|
+
}
|
|
671
|
+
const capabilites = (_a = channel.data) === null || _a === void 0 ? void 0 : _a.own_capabilities;
|
|
672
|
+
return capabilites.indexOf('read-events') !== -1;
|
|
673
|
+
}
|
|
661
674
|
}
|
|
662
675
|
ChannelService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: ChannelService, deps: [{ token: ChatClientService }, { token: i0.ApplicationRef }, { token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
663
676
|
ChannelService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: ChannelService, providedIn: 'root' });
|
|
@@ -1014,6 +1027,8 @@ const en = {
|
|
|
1014
1027
|
failed: 'failed',
|
|
1015
1028
|
retry: 'retry',
|
|
1016
1029
|
test: 'success',
|
|
1030
|
+
'Sending links is not allowed in this conversation': 'Sending links is not allowed in this conversation',
|
|
1031
|
+
"You can't send messages in this channel": "You can't send messages in this channel",
|
|
1017
1032
|
},
|
|
1018
1033
|
};
|
|
1019
1034
|
|
|
@@ -1114,8 +1129,10 @@ class TextareaDirective {
|
|
|
1114
1129
|
this.send = new EventEmitter();
|
|
1115
1130
|
this.userMentions = new EventEmitter();
|
|
1116
1131
|
this.subscriptions = [];
|
|
1132
|
+
this.unpropagatedChanges = [];
|
|
1117
1133
|
}
|
|
1118
1134
|
ngOnChanges(changes) {
|
|
1135
|
+
this.unpropagatedChanges.push(changes);
|
|
1119
1136
|
if (!this.componentRef) {
|
|
1120
1137
|
return;
|
|
1121
1138
|
}
|
|
@@ -1127,6 +1144,11 @@ class TextareaDirective {
|
|
|
1127
1144
|
if (this.componentRef.instance.userMentions) {
|
|
1128
1145
|
this.subscriptions.push(this.componentRef.instance.userMentions.subscribe((value) => this.userMentions.next(value)));
|
|
1129
1146
|
}
|
|
1147
|
+
this.componentRef.instance.areMentionsEnabled = this.areMentionsEnabled;
|
|
1148
|
+
this.componentRef.instance.mentionAutocompleteItemTemplate =
|
|
1149
|
+
this.mentionAutocompleteItemTemplate;
|
|
1150
|
+
this.componentRef.instance.mentionScope = this.mentionScope;
|
|
1151
|
+
this.componentRef.instance.value = this.value;
|
|
1130
1152
|
}
|
|
1131
1153
|
}
|
|
1132
1154
|
if (changes.areMentionsEnabled) {
|
|
@@ -1143,8 +1165,11 @@ class TextareaDirective {
|
|
|
1143
1165
|
this.componentRef.instance.value = this.value;
|
|
1144
1166
|
}
|
|
1145
1167
|
// ngOnChanges not called for dynamic components since we don't use template binding
|
|
1168
|
+
let changesToPropagate = {};
|
|
1169
|
+
this.unpropagatedChanges.forEach((c) => (changesToPropagate = Object.assign(Object.assign({}, changesToPropagate), c)));
|
|
1146
1170
|
// eslint-disable-next-line @angular-eslint/no-lifecycle-call
|
|
1147
|
-
this.componentRef.instance.ngOnChanges(
|
|
1171
|
+
this.componentRef.instance.ngOnChanges(changesToPropagate);
|
|
1172
|
+
this.unpropagatedChanges = [];
|
|
1148
1173
|
}
|
|
1149
1174
|
}
|
|
1150
1175
|
TextareaDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: TextareaDirective, deps: [{ token: i0.ViewContainerRef }], target: i0.ɵɵFactoryTarget.Directive });
|
|
@@ -1220,17 +1245,25 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImpor
|
|
|
1220
1245
|
}], ctorParameters: function () { return [{ type: AttachmentService }]; } });
|
|
1221
1246
|
|
|
1222
1247
|
class MessageInputComponent {
|
|
1223
|
-
constructor(channelService, notificationService, attachmentService, configService, textareaType, componentFactoryResolver) {
|
|
1248
|
+
constructor(channelService, notificationService, attachmentService, configService, textareaType, componentFactoryResolver, cdRef) {
|
|
1224
1249
|
this.channelService = channelService;
|
|
1225
1250
|
this.notificationService = notificationService;
|
|
1226
1251
|
this.attachmentService = attachmentService;
|
|
1227
1252
|
this.configService = configService;
|
|
1228
1253
|
this.textareaType = textareaType;
|
|
1229
1254
|
this.componentFactoryResolver = componentFactoryResolver;
|
|
1255
|
+
this.cdRef = cdRef;
|
|
1230
1256
|
this.messageUpdate = new EventEmitter();
|
|
1231
1257
|
this.textareaValue = '';
|
|
1232
1258
|
this.mentionedUsers = [];
|
|
1233
1259
|
this.subscriptions = [];
|
|
1260
|
+
this.isViewInited = false;
|
|
1261
|
+
this.subscriptions.push(this.attachmentService.attachmentUploadInProgressCounter$.subscribe((counter) => {
|
|
1262
|
+
if (counter === 0 && this.hideNotification) {
|
|
1263
|
+
this.hideNotification();
|
|
1264
|
+
this.hideNotification = undefined;
|
|
1265
|
+
}
|
|
1266
|
+
}));
|
|
1234
1267
|
this.subscriptions.push(this.channelService.activeChannel$.subscribe((channel) => {
|
|
1235
1268
|
var _a;
|
|
1236
1269
|
this.textareaValue = '';
|
|
@@ -1239,12 +1272,12 @@ class MessageInputComponent {
|
|
|
1239
1272
|
if (capabilities) {
|
|
1240
1273
|
this.isFileUploadAuthorized =
|
|
1241
1274
|
capabilities.indexOf('upload-file') !== -1;
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1275
|
+
this.canSendLinks = capabilities.indexOf('send-links') !== -1;
|
|
1276
|
+
this.canSendMessages = capabilities.indexOf('send-message') !== -1;
|
|
1277
|
+
if (this.isViewInited) {
|
|
1278
|
+
this.cdRef.detectChanges();
|
|
1279
|
+
this.initTextarea();
|
|
1280
|
+
}
|
|
1248
1281
|
}
|
|
1249
1282
|
}));
|
|
1250
1283
|
this.attachmentUploads$ = this.attachmentService.attachmentUploads$;
|
|
@@ -1257,10 +1290,9 @@ class MessageInputComponent {
|
|
|
1257
1290
|
this.configService.mentionAutocompleteItemTemplate;
|
|
1258
1291
|
this.mentionScope = this.configService.mentionScope;
|
|
1259
1292
|
}
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
this.
|
|
1263
|
-
this.textareaAnchor.viewContainerRef.createComponent(componentFactory);
|
|
1293
|
+
ngAfterViewInit() {
|
|
1294
|
+
this.isViewInited = true;
|
|
1295
|
+
this.initTextarea();
|
|
1264
1296
|
}
|
|
1265
1297
|
ngOnChanges(changes) {
|
|
1266
1298
|
if (changes.message) {
|
|
@@ -1312,6 +1344,10 @@ class MessageInputComponent {
|
|
|
1312
1344
|
if (!text && (!attachments || attachments.length === 0)) {
|
|
1313
1345
|
return;
|
|
1314
1346
|
}
|
|
1347
|
+
if (this.containsLinks && !this.canSendLinks) {
|
|
1348
|
+
this.notificationService.addTemporaryNotification('streamChat.Sending links is not allowed in this conversation');
|
|
1349
|
+
return;
|
|
1350
|
+
}
|
|
1315
1351
|
if (!this.isUpdate) {
|
|
1316
1352
|
this.textareaValue = '';
|
|
1317
1353
|
}
|
|
@@ -1331,6 +1367,9 @@ class MessageInputComponent {
|
|
|
1331
1367
|
}
|
|
1332
1368
|
});
|
|
1333
1369
|
}
|
|
1370
|
+
get containsLinks() {
|
|
1371
|
+
return /(?:(?:https?|ftp):\/\/)?[\w/\-?=%.]+\.[\w/\-&?=%.]+/.test(this.textareaValue);
|
|
1372
|
+
}
|
|
1334
1373
|
get accept() {
|
|
1335
1374
|
var _a;
|
|
1336
1375
|
return this.acceptedFileTypes ? (_a = this.acceptedFileTypes) === null || _a === void 0 ? void 0 : _a.join(',') : '';
|
|
@@ -1347,9 +1386,18 @@ class MessageInputComponent {
|
|
|
1347
1386
|
get isUpdate() {
|
|
1348
1387
|
return !!this.message;
|
|
1349
1388
|
}
|
|
1389
|
+
initTextarea() {
|
|
1390
|
+
if (!this.canSendMessages || this.textareaRef || !this.textareaAnchor) {
|
|
1391
|
+
return;
|
|
1392
|
+
}
|
|
1393
|
+
const componentFactory = this.componentFactoryResolver.resolveComponentFactory(this.textareaType);
|
|
1394
|
+
this.textareaRef =
|
|
1395
|
+
this.textareaAnchor.viewContainerRef.createComponent(componentFactory);
|
|
1396
|
+
this.cdRef.detectChanges();
|
|
1397
|
+
}
|
|
1350
1398
|
}
|
|
1351
|
-
MessageInputComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: MessageInputComponent, deps: [{ token: ChannelService }, { token: NotificationService }, { token: AttachmentService }, { token: MessageInputConfigService }, { token: textareaInjectionToken }, { token: i0.ComponentFactoryResolver }], target: i0.ɵɵFactoryTarget.Component });
|
|
1352
|
-
MessageInputComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.5", type: MessageInputComponent, selector: "stream-message-input", inputs: { isFileUploadEnabled: "isFileUploadEnabled", areMentionsEnabled: "areMentionsEnabled", mentionScope: "mentionScope", mentionAutocompleteItemTemplate: "mentionAutocompleteItemTemplate", acceptedFileTypes: "acceptedFileTypes", isMultipleFileUploadEnabled: "isMultipleFileUploadEnabled", message: "message" }, outputs: { messageUpdate: "messageUpdate" }, providers: [AttachmentService], viewQueries: [{ propertyName: "fileInput", first: true, predicate: ["fileInput"], descendants: true }, { propertyName: "textareaAnchor", first: true, predicate: TextareaDirective, descendants: true
|
|
1399
|
+
MessageInputComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: MessageInputComponent, deps: [{ token: ChannelService }, { token: NotificationService }, { token: AttachmentService }, { token: MessageInputConfigService }, { token: textareaInjectionToken }, { token: i0.ComponentFactoryResolver }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
|
|
1400
|
+
MessageInputComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.5", type: MessageInputComponent, selector: "stream-message-input", inputs: { isFileUploadEnabled: "isFileUploadEnabled", areMentionsEnabled: "areMentionsEnabled", mentionScope: "mentionScope", mentionAutocompleteItemTemplate: "mentionAutocompleteItemTemplate", acceptedFileTypes: "acceptedFileTypes", isMultipleFileUploadEnabled: "isMultipleFileUploadEnabled", message: "message" }, outputs: { messageUpdate: "messageUpdate" }, providers: [AttachmentService], viewQueries: [{ propertyName: "fileInput", first: true, predicate: ["fileInput"], descendants: true }, { propertyName: "textareaAnchor", first: true, predicate: TextareaDirective, descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div\n class=\"str-chat__input-flat\"\n [class.str-chat__input-flat-has-attachments]=\"\n (attachmentUploads$ | async)!.length > 0\n \"\n>\n <div class=\"str-chat__input-flat-wrapper\">\n <div class=\"str-chat__input-flat--textarea-wrapper\">\n <stream-attachment-preview-list\n class=\"rfu-image-previewer-angular-host\"\n ></stream-attachment-preview-list>\n <div class=\"rta str-chat__textarea\">\n <ng-template\n *ngIf=\"canSendMessages; else notAllowed\"\n streamTextarea\n [(value)]=\"textareaValue\"\n (send)=\"messageSent()\"\n [componentRef]=\"textareaRef\"\n (userMentions)=\"mentionedUsers = $event\"\n [areMentionsEnabled]=\"areMentionsEnabled\"\n [mentionAutocompleteItemTemplate]=\"mentionAutocompleteItemTemplate\"\n [mentionScope]=\"mentionScope\"\n ></ng-template>\n <ng-template #notAllowed>\n <textarea\n disabled\n rows=\"1\"\n [value]=\"\n 'streamChat.You can\\'t send messages in this channel' | translate\n \"\n class=\"rta__textarea str-chat__textarea__textarea\"\n ></textarea>\n </ng-template>\n </div>\n <div\n *ngIf=\"isFileUploadEnabled && isFileUploadAuthorized && canSendMessages\"\n class=\"str-chat__fileupload-wrapper\"\n data-testid=\"file-upload-button\"\n >\n <div class=\"str-chat__tooltip\">\n {{ \"streamChat.Attach files\" | translate }}\n </div>\n <div class=\"rfu-file-upload-button\">\n <label>\n <input\n #fileInput\n type=\"file\"\n class=\"rfu-file-input\"\n data-testid=\"file-input\"\n [accept]=\"accept\"\n [multiple]=\"isMultipleFileUploadEnabled\"\n (change)=\"filesSelected(fileInput.files)\"\n />\n <span class=\"str-chat__input-flat-fileupload\">\n <stream-icon icon=\"file-upload\"></stream-icon>\n </span>\n </label>\n </div>\n </div>\n </div>\n <button\n *ngIf=\"canSendMessages\"\n data-testid=\"send-button\"\n class=\"str-chat__send-button\"\n (click)=\"messageSent()\"\n (keyup.enter)=\"messageSent()\"\n >\n <stream-icon icon=\"send\"></stream-icon>\n </button>\n </div>\n</div>\n", components: [{ type: AttachmentPreviewListComponent, selector: "stream-attachment-preview-list" }, { type: IconComponent, selector: "stream-icon", inputs: ["icon", "size"] }], directives: [{ type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: TextareaDirective, selector: "[streamTextarea]", inputs: ["componentRef", "areMentionsEnabled", "mentionAutocompleteItemTemplate", "mentionScope", "value"], outputs: ["valueChange", "send", "userMentions"] }], pipes: { "async": i3.AsyncPipe, "translate": i1.TranslatePipe } });
|
|
1353
1401
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: MessageInputComponent, decorators: [{
|
|
1354
1402
|
type: Component,
|
|
1355
1403
|
args: [{
|
|
@@ -1361,7 +1409,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImpor
|
|
|
1361
1409
|
}], ctorParameters: function () { return [{ type: ChannelService }, { type: NotificationService }, { type: AttachmentService }, { type: MessageInputConfigService }, { type: i0.Type, decorators: [{
|
|
1362
1410
|
type: Inject,
|
|
1363
1411
|
args: [textareaInjectionToken]
|
|
1364
|
-
}] }, { type: i0.ComponentFactoryResolver }]; }, propDecorators: { isFileUploadEnabled: [{
|
|
1412
|
+
}] }, { type: i0.ComponentFactoryResolver }, { type: i0.ChangeDetectorRef }]; }, propDecorators: { isFileUploadEnabled: [{
|
|
1365
1413
|
type: Input
|
|
1366
1414
|
}], areMentionsEnabled: [{
|
|
1367
1415
|
type: Input
|
|
@@ -1382,7 +1430,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImpor
|
|
|
1382
1430
|
args: ['fileInput']
|
|
1383
1431
|
}], textareaAnchor: [{
|
|
1384
1432
|
type: ViewChild,
|
|
1385
|
-
args: [TextareaDirective, { static:
|
|
1433
|
+
args: [TextareaDirective, { static: false }]
|
|
1386
1434
|
}] } });
|
|
1387
1435
|
|
|
1388
1436
|
class ModalComponent {
|
|
@@ -1491,6 +1539,10 @@ class MessageActionsBoxComponent {
|
|
|
1491
1539
|
this.displayedActionsCount = new EventEmitter();
|
|
1492
1540
|
this.isEditing = new EventEmitter();
|
|
1493
1541
|
this.isEditModalOpen = false;
|
|
1542
|
+
this.modalClosed = () => {
|
|
1543
|
+
this.isEditModalOpen = false;
|
|
1544
|
+
this.isEditing.emit(false);
|
|
1545
|
+
};
|
|
1494
1546
|
}
|
|
1495
1547
|
ngOnChanges(changes) {
|
|
1496
1548
|
if (changes.isMine || changes.enabledActions) {
|
|
@@ -1564,10 +1616,6 @@ class MessageActionsBoxComponent {
|
|
|
1564
1616
|
var _a;
|
|
1565
1617
|
(_a = this.messageInput) === null || _a === void 0 ? void 0 : _a.messageSent();
|
|
1566
1618
|
}
|
|
1567
|
-
modalClosed() {
|
|
1568
|
-
this.isEditModalOpen = false;
|
|
1569
|
-
this.isEditing.emit(false);
|
|
1570
|
-
}
|
|
1571
1619
|
deleteClicked() {
|
|
1572
1620
|
return __awaiter(this, void 0, void 0, function* () {
|
|
1573
1621
|
try {
|
|
@@ -1580,7 +1628,7 @@ class MessageActionsBoxComponent {
|
|
|
1580
1628
|
}
|
|
1581
1629
|
}
|
|
1582
1630
|
MessageActionsBoxComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: MessageActionsBoxComponent, deps: [{ token: ChatClientService }, { token: NotificationService }, { token: ChannelService }], target: i0.ɵɵFactoryTarget.Component });
|
|
1583
|
-
MessageActionsBoxComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.5", type: MessageActionsBoxComponent, selector: "stream-message-actions-box", inputs: { isOpen: "isOpen", isMine: "isMine", message: "message", enabledActions: "enabledActions" }, outputs: { displayedActionsCount: "displayedActionsCount", isEditing: "isEditing" }, viewQueries: [{ propertyName: "messageInput", first: true, predicate: MessageInputComponent, descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div\n data-testid=\"action-box\"\n class=\"str-chat__message-actions-box\"\n [class.str-chat__message-actions-box--open]=\"isOpen\"\n [class.str-chat__message-actions-box--mine]=\"isMine\"\n>\n <ul class=\"str-chat__message-actions-list\">\n <button\n data-testid=\"quote-action\"\n *ngIf=\"isQuoteVisible\"\n (click)=\"quoteClicked()\"\n >\n <li class=\"str-chat__message-actions-list-item\">\n {{ \"streamChat.Reply\" | translate }}\n </li>\n </button>\n <button\n data-testid=\"pin-action\"\n *ngIf=\"isPinVisible\"\n (click)=\"pinClicked()\"\n >\n <li class=\"str-chat__message-actions-list-item\">\n {{\n (message?.pinned ? \"streamChat.Unpin\" : \"streamChat.Pin\") | translate\n }}\n </li>\n </button>\n <button\n data-testid=\"flag-action\"\n *ngIf=\"isFlagVisible\"\n (click)=\"flagClicked()\"\n >\n <li class=\"str-chat__message-actions-list-item\">\n {{ \"streamChat.Flag\" | translate }}\n </li>\n </button>\n <button\n data-testid=\"mute-action\"\n *ngIf=\"isMuteVisible\"\n (click)=\"muteClicked()\"\n >\n <li class=\"str-chat__message-actions-list-item\">\n {{ \"streamChat.Mute\" | translate }}\n </li>\n </button>\n <button\n data-testid=\"edit-action\"\n *ngIf=\"isEditVisible\"\n (click)=\"editClicked()\"\n >\n <li class=\"str-chat__message-actions-list-item\">\n {{ \"streamChat.Edit Message\" | translate }}\n </li>\n </button>\n <button\n data-testid=\"delete-action\"\n *ngIf=\"isDeleteVisible\"\n (click)=\"deleteClicked()\"\n >\n <li class=\"str-chat__message-actions-list-item\">\n {{ \"streamChat.Delete\" | translate }}\n </li>\n </button>\n </ul>\n</div>\n\n<stream-modal\n [isOpen]=\"isEditModalOpen\"\n (isOpenChange)=\"\n isEditModalOpen = $event; isEditModalOpen ? '' : modalClosed()\n \"\n>\n <div class=\"str-chat__edit-message-form\" *ngIf=\"isEditModalOpen\">\n <stream-message-input\n
|
|
1631
|
+
MessageActionsBoxComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.5", type: MessageActionsBoxComponent, selector: "stream-message-actions-box", inputs: { messageInputTemplate: "messageInputTemplate", isOpen: "isOpen", isMine: "isMine", message: "message", enabledActions: "enabledActions" }, outputs: { displayedActionsCount: "displayedActionsCount", isEditing: "isEditing" }, viewQueries: [{ propertyName: "messageInput", first: true, predicate: MessageInputComponent, descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div\n data-testid=\"action-box\"\n class=\"str-chat__message-actions-box\"\n [class.str-chat__message-actions-box--open]=\"isOpen\"\n [class.str-chat__message-actions-box--mine]=\"isMine\"\n>\n <ul class=\"str-chat__message-actions-list\">\n <button\n data-testid=\"quote-action\"\n *ngIf=\"isQuoteVisible\"\n (click)=\"quoteClicked()\"\n >\n <li class=\"str-chat__message-actions-list-item\">\n {{ \"streamChat.Reply\" | translate }}\n </li>\n </button>\n <button\n data-testid=\"pin-action\"\n *ngIf=\"isPinVisible\"\n (click)=\"pinClicked()\"\n >\n <li class=\"str-chat__message-actions-list-item\">\n {{\n (message?.pinned ? \"streamChat.Unpin\" : \"streamChat.Pin\") | translate\n }}\n </li>\n </button>\n <button\n data-testid=\"flag-action\"\n *ngIf=\"isFlagVisible\"\n (click)=\"flagClicked()\"\n >\n <li class=\"str-chat__message-actions-list-item\">\n {{ \"streamChat.Flag\" | translate }}\n </li>\n </button>\n <button\n data-testid=\"mute-action\"\n *ngIf=\"isMuteVisible\"\n (click)=\"muteClicked()\"\n >\n <li class=\"str-chat__message-actions-list-item\">\n {{ \"streamChat.Mute\" | translate }}\n </li>\n </button>\n <button\n data-testid=\"edit-action\"\n *ngIf=\"isEditVisible\"\n (click)=\"editClicked()\"\n >\n <li class=\"str-chat__message-actions-list-item\">\n {{ \"streamChat.Edit Message\" | translate }}\n </li>\n </button>\n <button\n data-testid=\"delete-action\"\n *ngIf=\"isDeleteVisible\"\n (click)=\"deleteClicked()\"\n >\n <li class=\"str-chat__message-actions-list-item\">\n {{ \"streamChat.Delete\" | translate }}\n </li>\n </button>\n </ul>\n</div>\n\n<stream-modal\n [isOpen]=\"isEditModalOpen\"\n (isOpenChange)=\"\n isEditModalOpen = $event; isEditModalOpen ? '' : modalClosed()\n \"\n>\n <div class=\"str-chat__edit-message-form\" *ngIf=\"isEditModalOpen\">\n <ng-container *ngIf=\"messageInputTemplate; else defaultInput\">\n <ng-container\n *ngTemplateOutlet=\"\n messageInputTemplate;\n context: {\n message: message,\n messageUpdateHandler: modalClosed\n }\n \"\n ></ng-container>\n </ng-container>\n <ng-template #defaultInput>\n <stream-message-input\n [message]=\"message\"\n (messageUpdate)=\"modalClosed()\"\n ></stream-message-input>\n </ng-template>\n <stream-notification-list></stream-notification-list>\n <div class=\"str-chat__message-team-form-footer\">\n <div></div>\n <div>\n <button translate data-testid=\"cancel-button\" (click)=\"modalClosed()\">\n streamChat.Cancel\n </button>\n <button\n type=\"submit\"\n translate\n data-testid=\"send-button\"\n (click)=\"sendClicked()\"\n (keyup.enter)=\"sendClicked()\"\n >\n streamChat.Send\n </button>\n </div>\n </div>\n </div>\n</stream-modal>\n", components: [{ type: ModalComponent, selector: "stream-modal", inputs: ["isOpen"], outputs: ["isOpenChange"] }, { type: MessageInputComponent, selector: "stream-message-input", inputs: ["isFileUploadEnabled", "areMentionsEnabled", "mentionScope", "mentionAutocompleteItemTemplate", "acceptedFileTypes", "isMultipleFileUploadEnabled", "message"], outputs: ["messageUpdate"] }, { type: NotificationListComponent, selector: "stream-notification-list" }], directives: [{ type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i3.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet"] }, { type: i1.TranslateDirective, selector: "[translate],[ngx-translate]", inputs: ["translate", "translateParams"] }], pipes: { "translate": i1.TranslatePipe } });
|
|
1584
1632
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: MessageActionsBoxComponent, decorators: [{
|
|
1585
1633
|
type: Component,
|
|
1586
1634
|
args: [{
|
|
@@ -1588,7 +1636,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImpor
|
|
|
1588
1636
|
templateUrl: './message-actions-box.component.html',
|
|
1589
1637
|
styles: [],
|
|
1590
1638
|
}]
|
|
1591
|
-
}], ctorParameters: function () { return [{ type: ChatClientService }, { type: NotificationService }, { type: ChannelService }]; }, propDecorators: {
|
|
1639
|
+
}], ctorParameters: function () { return [{ type: ChatClientService }, { type: NotificationService }, { type: ChannelService }]; }, propDecorators: { messageInputTemplate: [{
|
|
1640
|
+
type: Input
|
|
1641
|
+
}], isOpen: [{
|
|
1592
1642
|
type: Input
|
|
1593
1643
|
}], isMine: [{
|
|
1594
1644
|
type: Input
|
|
@@ -1689,7 +1739,16 @@ class ChannelHeaderComponent {
|
|
|
1689
1739
|
constructor(channelService, channelListToggleService) {
|
|
1690
1740
|
this.channelService = channelService;
|
|
1691
1741
|
this.channelListToggleService = channelListToggleService;
|
|
1692
|
-
this.channelService.activeChannel$.subscribe((c) =>
|
|
1742
|
+
this.channelService.activeChannel$.subscribe((c) => {
|
|
1743
|
+
var _a, _b;
|
|
1744
|
+
this.activeChannel = c;
|
|
1745
|
+
const capabilities = (_b = (_a = this.activeChannel) === null || _a === void 0 ? void 0 : _a.data) === null || _b === void 0 ? void 0 : _b.own_capabilities;
|
|
1746
|
+
if (!capabilities) {
|
|
1747
|
+
return;
|
|
1748
|
+
}
|
|
1749
|
+
this.canReceiveConnectEvents =
|
|
1750
|
+
capabilities.indexOf('connect-events') !== -1;
|
|
1751
|
+
});
|
|
1693
1752
|
}
|
|
1694
1753
|
toggleMenu(event) {
|
|
1695
1754
|
event.stopPropagation();
|
|
@@ -1705,7 +1764,7 @@ class ChannelHeaderComponent {
|
|
|
1705
1764
|
}
|
|
1706
1765
|
}
|
|
1707
1766
|
ChannelHeaderComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: ChannelHeaderComponent, deps: [{ token: ChannelService }, { token: ChannelListToggleService }], target: i0.ɵɵFactoryTarget.Component });
|
|
1708
|
-
ChannelHeaderComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.5", type: ChannelHeaderComponent, selector: "stream-channel-header", ngImport: i0, template: "<div class=\"str-chat__header-livestream\">\n <div\n class=\"str-chat__header-hamburger\"\n (click)=\"toggleMenu($event)\"\n (keyup.enter)=\"toggleMenu($event)\"\n >\n <span class=\"str-chat__header-hamburger--line\"></span>\n <span class=\"str-chat__header-hamburger--line\"></span>\n <span class=\"str-chat__header-hamburger--line\"></span>\n </div>\n <stream-avatar\n imageUrl=\"{{ activeChannel?.data?.image }}\"\n name=\"{{ activeChannel?.data?.name }}\"\n ></stream-avatar>\n <div class=\"str-chat__header-livestream-left\">\n <p class=\"str-chat__header-livestream-left--title\">\n {{ activeChannel?.data?.name }}\n </p>\n <p class=\"str-chat__header-livestream-left--members\">\n {{'streamChat.{{ memberCount }} members' | translate:memberCountParam}}\n {{'streamChat.{{ watcherCount }} online'
|
|
1767
|
+
ChannelHeaderComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.5", type: ChannelHeaderComponent, selector: "stream-channel-header", ngImport: i0, template: "<div class=\"str-chat__header-livestream\">\n <div\n class=\"str-chat__header-hamburger\"\n (click)=\"toggleMenu($event)\"\n (keyup.enter)=\"toggleMenu($event)\"\n >\n <span class=\"str-chat__header-hamburger--line\"></span>\n <span class=\"str-chat__header-hamburger--line\"></span>\n <span class=\"str-chat__header-hamburger--line\"></span>\n </div>\n <stream-avatar\n imageUrl=\"{{ activeChannel?.data?.image }}\"\n name=\"{{ activeChannel?.data?.name }}\"\n ></stream-avatar>\n <div class=\"str-chat__header-livestream-left\">\n <p data-testid=\"name\" class=\"str-chat__header-livestream-left--title\">\n {{ activeChannel?.data?.name }}\n </p>\n <p data-testid=\"info\" class=\"str-chat__header-livestream-left--members\">\n {{'streamChat.{{ memberCount }} members' | translate:memberCountParam}}\n {{canReceiveConnectEvents ? ('streamChat.{{ watcherCount }} online' |\n translate:watcherCountParam) : ''}}\n </p>\n </div>\n</div>\n", components: [{ type: AvatarComponent, selector: "stream-avatar", inputs: ["name", "imageUrl", "size"] }], pipes: { "translate": i1.TranslatePipe } });
|
|
1709
1768
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: ChannelHeaderComponent, decorators: [{
|
|
1710
1769
|
type: Component,
|
|
1711
1770
|
args: [{
|
|
@@ -1722,20 +1781,24 @@ class ChannelPreviewComponent {
|
|
|
1722
1781
|
this.isUnread = false;
|
|
1723
1782
|
this.latestMessage = 'Nothing yet...';
|
|
1724
1783
|
this.subscriptions = [];
|
|
1784
|
+
this.canSendReadEvents = true;
|
|
1725
1785
|
}
|
|
1726
1786
|
ngOnInit() {
|
|
1727
|
-
var _a, _b;
|
|
1787
|
+
var _a, _b, _c, _d;
|
|
1728
1788
|
this.subscriptions.push(this.channelService.activeChannel$.subscribe((activeChannel) => { var _a; return (this.isActive = (activeChannel === null || activeChannel === void 0 ? void 0 : activeChannel.id) === ((_a = this.channel) === null || _a === void 0 ? void 0 : _a.id)); }));
|
|
1729
1789
|
const messages = (_b = (_a = this.channel) === null || _a === void 0 ? void 0 : _a.state) === null || _b === void 0 ? void 0 : _b.messages;
|
|
1730
1790
|
if (messages && messages.length > 0) {
|
|
1731
1791
|
this.setLatestMessage(messages[messages.length - 1]);
|
|
1732
1792
|
}
|
|
1733
|
-
this.isUnread = !!this.channel.countUnread();
|
|
1793
|
+
this.isUnread = !!this.channel.countUnread() && this.canSendReadEvents;
|
|
1794
|
+
const capabilities = ((_d = (_c = this.channel) === null || _c === void 0 ? void 0 : _c.data) === null || _d === void 0 ? void 0 : _d.own_capabilities) || [];
|
|
1795
|
+
this.canSendReadEvents = capabilities.indexOf('read-events') !== -1;
|
|
1734
1796
|
this.subscriptions.push(this.channel.on('message.new', this.handleMessageEvent.bind(this)));
|
|
1735
1797
|
this.subscriptions.push(this.channel.on('message.updated', this.handleMessageEvent.bind(this)));
|
|
1736
1798
|
this.subscriptions.push(this.channel.on('message.deleted', this.handleMessageEvent.bind(this)));
|
|
1737
1799
|
this.subscriptions.push(this.channel.on('channel.truncated', this.handleMessageEvent.bind(this)));
|
|
1738
|
-
this.subscriptions.push(this.channel.on('message.read', () => (this.isUnread =
|
|
1800
|
+
this.subscriptions.push(this.channel.on('message.read', () => (this.isUnread =
|
|
1801
|
+
!!this.channel.countUnread() && this.canSendReadEvents)));
|
|
1739
1802
|
}
|
|
1740
1803
|
ngOnDestroy() {
|
|
1741
1804
|
this.subscriptions.forEach((s) => s.unsubscribe());
|
|
@@ -1766,7 +1829,7 @@ class ChannelPreviewComponent {
|
|
|
1766
1829
|
return;
|
|
1767
1830
|
}
|
|
1768
1831
|
this.setLatestMessage(event.message);
|
|
1769
|
-
this.isUnread = !!this.channel.countUnread();
|
|
1832
|
+
this.isUnread = !!this.channel.countUnread() && this.canSendReadEvents;
|
|
1770
1833
|
}
|
|
1771
1834
|
setLatestMessage(message) {
|
|
1772
1835
|
if (message === null || message === void 0 ? void 0 : message.deleted_at) {
|
|
@@ -2178,7 +2241,7 @@ class MessageComponent {
|
|
|
2178
2241
|
}
|
|
2179
2242
|
}
|
|
2180
2243
|
MessageComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: MessageComponent, deps: [{ token: ChatClientService }, { token: ChannelService }], target: i0.ɵɵFactoryTarget.Component });
|
|
2181
|
-
MessageComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.5", type: MessageComponent, selector: "stream-message", inputs: { message: "message", enabledMessageActions: "enabledMessageActions", areReactionsEnabled: "areReactionsEnabled", canReactToMessage: "canReactToMessage", isLastSentMessage: "isLastSentMessage" }, viewQueries: [{ propertyName: "container", first: true, predicate: ["container"], descendants: true }], ngImport: i0, template: "<div\n #container\n class=\"str-chat__message-simple str-chat__message str-chat__message--{{\n message?.type\n }} str-chat__message--{{ message?.status }} {{\n message?.text ? 'str-chat__message--has-text' : 'has-no-text'\n }}\"\n [class.str-chat__message--me]=\"isSentByCurrentUser\"\n [class.str-chat__message-simple--me]=\"isSentByCurrentUser\"\n [class.mobile-press]=\"isPressedOnMobile\"\n [class.str-chat__message--has-attachment]=\"hasAttachment\"\n [class.str-chat__message--with-reactions]=\"\n areReactionsEnabled && hasReactions\n \"\n data-testid=\"message-container\"\n>\n <ng-container *ngIf=\"!message?.deleted_at; else deletedMessage\">\n <ng-container *ngIf=\"message?.type !== 'system'; else systemMessage\">\n <ng-container\n *ngIf=\"\n isSentByCurrentUser &&\n ((isLastSentMessage && message?.status === 'received') ||\n message?.status === 'sending')\n \"\n >\n <ng-container *ngIf=\"message?.status === 'sending'; else sentStatus\">\n <ng-container *ngTemplateOutlet=\"sendingStatus\"></ng-container>\n </ng-container>\n <ng-template #sentStatus>\n <ng-container *ngIf=\"isMessageDeliveredAndRead; else deliveredStatus\">\n <ng-container *ngTemplateOutlet=\"readStatus\"></ng-container>\n </ng-container>\n </ng-template>\n </ng-container>\n <stream-avatar\n data-testid=\"avatar\"\n class=\"str-chat-angular__avatar-host\"\n [imageUrl]=\"message?.user?.image\"\n [name]=\"message?.user?.name || message?.user?.id\"\n ></stream-avatar>\n <div class=\"str-chat__message-inner\">\n <div\n class=\"str-chat__message-simple__actions\"\n data-testid=\"message-options\"\n *ngIf=\"areOptionsVisible\"\n >\n <div\n data-testid=\"message-actions-container\"\n class=\"\n str-chat__message-simple__actions__action\n str-chat__message-simple__actions__action--options\n \"\n [class.str-chat-angular__message-simple__actions__action--options--editing]=\"\n isEditing\n \"\n >\n <stream-message-actions-box\n [isOpen]=\"isActionBoxOpen\"\n [isMine]=\"isSentByCurrentUser\"\n [enabledActions]=\"enabledMessageActions\"\n [message]=\"message\"\n (displayedActionsCount)=\"visibleMessageActionsCount = $event\"\n (isEditing)=\"isEditing = $event; isActionBoxOpen = !isEditing\"\n ></stream-message-actions-box>\n <stream-icon\n *ngIf=\"visibleMessageActionsCount > 0\"\n data-testid=\"action-icon\"\n icon=\"action-icon\"\n (keyup.enter)=\"isActionBoxOpen = !isActionBoxOpen\"\n (click)=\"isActionBoxOpen = !isActionBoxOpen\"\n ></stream-icon>\n </div>\n <div\n *ngIf=\"areReactionsEnabled && canReactToMessage\"\n class=\"\n str-chat__message-simple__actions__action\n str-chat__message-simple__actions__action--reactions\n \"\n data-testid=\"reaction-icon\"\n (click)=\"isReactionSelectorOpen = !isReactionSelectorOpen\"\n (keyup.enter)=\"isReactionSelectorOpen = !isReactionSelectorOpen\"\n >\n <stream-icon icon=\"reaction-icon\"></stream-icon>\n </div>\n </div>\n <stream-message-reactions\n *ngIf=\"areReactionsEnabled\"\n [messageReactionCounts]=\"message?.reaction_counts || {}\"\n [latestReactions]=\"message?.latest_reactions || []\"\n [(isSelectorOpen)]=\"isReactionSelectorOpen\"\n [messageId]=\"message?.id\"\n [ownReactions]=\"message?.own_reactions || []\"\n ></stream-message-reactions>\n <stream-attachment-list\n *ngIf=\"hasAttachment\"\n [attachments]=\"message!.attachments!\"\n ></stream-attachment-list>\n <div class=\"str-chat__message-text\" *ngIf=\"message?.text\">\n <div\n data-testid=\"inner-message\"\n class=\"\n str-chat__message-text-inner str-chat__message-simple-text-inner\n \"\n [class.str-chat__message-light-text-inner--has-attachment]=\"\n hasAttachment\n \"\n (click)=\"\n message?.status === 'failed' && message?.errorStatusCode !== 403\n ? resendMessage()\n : undefined\n \"\n (keyup.enter)=\"\n message?.status === 'failed' && message?.errorStatusCode !== 403\n ? resendMessage()\n : undefined\n \"\n >\n <div\n data-testid=\"client-error-message\"\n *ngIf=\"message?.type === 'error'\"\n class=\"str-chat__simple-message--error-message\"\n >\n {{ \"streamChat.Error \u00B7 Unsent\" | translate }}\n </div>\n <div\n data-testid=\"error-message\"\n *ngIf=\"message?.status === 'failed'\"\n class=\"str-chat__simple-message--error-message\"\n >\n {{\n (message?.errorStatusCode === 403\n ? \"streamChat.Message Failed \u00B7 Unauthorized\"\n : \"streamChat.Message Failed \u00B7 Click to try again\"\n ) | translate\n }}\n </div>\n <div\n (click)=\"textClicked()\"\n (keyup.enter)=\"textClicked()\"\n data-testid=\"text\"\n [innerHTML]=\"\n message?.html || message?.text\n | highlightMentions: message?.mentioned_users\n \"\n ></div>\n </div>\n </div>\n <div class=\"str-chat__message-data str-chat__message-simple-data\">\n <span\n data-testid=\"sender\"\n *ngIf=\"!isSentByCurrentUser\"\n class=\"str-chat__message-simple-name\"\n >\n {{ message?.user?.name ? message?.user?.name : message?.user?.id }}\n </span>\n <span data-testid=\"date\" class=\"str-chat__message-simple-timestamp\">\n {{ parsedDate }}\n </span>\n </div>\n </div>\n </ng-container>\n </ng-container>\n</div>\n\n<ng-template #sendingStatus>\n <span class=\"str-chat__message-simple-status\" data-testid=\"sending-indicator\">\n <div class=\"str-chat__tooltip\">\n {{ \"streamChat.Sending...\" | translate }}\n </div>\n <stream-loading-indicator\n data-testid=\"loading-indicator\"\n ></stream-loading-indicator>\n </span>\n</ng-template>\n<ng-template #readStatus>\n <span class=\"str-chat__message-simple-status\" data-testid=\"read-indicator\">\n <div class=\"str-chat__tooltip\" data-testid=\"read-by-tooltip\">\n {{ readByText }}\n </div>\n <stream-avatar\n class=\"str-chat-angular__avatar-host\"\n data-test-id=\"last-read-user-avatar\"\n [size]=\"15\"\n [imageUrl]=\"lastReadUser?.image\"\n [name]=\"lastReadUser?.name || lastReadUser?.id\"\n ></stream-avatar>\n <span\n data-test-id=\"read-by-length\"\n *ngIf=\"isReadByMultipleUsers\"\n class=\"str-chat__message-simple-status-number\"\n >\n {{ (message?.readBy)!.length }}\n </span>\n </span>\n</ng-template>\n<ng-template #deliveredStatus>\n <span\n class=\"str-chat__message-simple-status\"\n data-testid=\"delivered-indicator\"\n >\n <div class=\"str-chat__tooltip\">\n {{ \"streamChat.Delivered\" | translate }}\n </div>\n <stream-icon\n data-testid=\"delivered-icon\"\n icon=\"delivered-icon\"\n ></stream-icon>\n </span>\n</ng-template>\n\n<ng-template #deletedMessage>\n <div data-testid=\"message-deleted-component\">\n <div class=\"str-chat__message--deleted-inner\" translate>\n streamChat.This message was deleted...\n </div>\n </div>\n</ng-template>\n\n<ng-template #systemMessage>\n <div data-testid=\"system-message\" class=\"str-chat__message--system\">\n <div class=\"str-chat__message--system__text\">\n <div class=\"str-chat__message--system__line\"></div>\n <p>{{ message?.text }}</p>\n <div class=\"str-chat__message--system__line\"></div>\n </div>\n <div class=\"str-chat__message--system__date\">\n {{ parsedDate }}\n </div>\n </div>\n</ng-template>\n", components: [{ type: AvatarComponent, selector: "stream-avatar", inputs: ["name", "imageUrl", "size"] }, { type: MessageActionsBoxComponent, selector: "stream-message-actions-box", inputs: ["isOpen", "isMine", "message", "enabledActions"], outputs: ["displayedActionsCount", "isEditing"] }, { type: IconComponent, selector: "stream-icon", inputs: ["icon", "size"] }, { type: MessageReactionsComponent, selector: "stream-message-reactions", inputs: ["messageId", "messageReactionCounts", "isSelectorOpen", "latestReactions", "ownReactions"], outputs: ["isSelectorOpenChange"] }, { type: AttachmentListComponent, selector: "stream-attachment-list", inputs: ["attachments"] }, { type: LoadingIndicatorComponent, selector: "stream-loading-indicator", inputs: ["size", "color"] }], directives: [{ type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i3.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet"] }, { type: i1.TranslateDirective, selector: "[translate],[ngx-translate]", inputs: ["translate", "translateParams"] }], pipes: { "translate": i1.TranslatePipe, "highlightMentions": HighlightMentionsPipe } });
|
|
2244
|
+
MessageComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.5", type: MessageComponent, selector: "stream-message", inputs: { messageInputTemplate: "messageInputTemplate", message: "message", enabledMessageActions: "enabledMessageActions", areReactionsEnabled: "areReactionsEnabled", canReactToMessage: "canReactToMessage", isLastSentMessage: "isLastSentMessage", canReceiveReadEvents: "canReceiveReadEvents" }, viewQueries: [{ propertyName: "container", first: true, predicate: ["container"], descendants: true }], ngImport: i0, template: "<div\n #container\n class=\"str-chat__message-simple str-chat__message str-chat__message--{{\n message?.type\n }} str-chat__message--{{ message?.status }} {{\n message?.text ? 'str-chat__message--has-text' : 'has-no-text'\n }}\"\n [class.str-chat__message--me]=\"isSentByCurrentUser\"\n [class.str-chat__message-simple--me]=\"isSentByCurrentUser\"\n [class.mobile-press]=\"isPressedOnMobile\"\n [class.str-chat__message--has-attachment]=\"hasAttachment\"\n [class.str-chat__message--with-reactions]=\"\n areReactionsEnabled && hasReactions\n \"\n data-testid=\"message-container\"\n>\n <ng-container *ngIf=\"!message?.deleted_at; else deletedMessage\">\n <ng-container *ngIf=\"message?.type !== 'system'; else systemMessage\">\n <ng-container\n *ngIf=\"\n isSentByCurrentUser &&\n ((isLastSentMessage && message?.status === 'received') ||\n message?.status === 'sending')\n \"\n >\n <ng-container *ngIf=\"message?.status === 'sending'; else sentStatus\">\n <ng-container *ngTemplateOutlet=\"sendingStatus\"></ng-container>\n </ng-container>\n <ng-template #sentStatus>\n <ng-container\n *ngIf=\"\n isMessageDeliveredAndRead && canReceiveReadEvents;\n else deliveredStatus\n \"\n >\n <ng-container *ngTemplateOutlet=\"readStatus\"></ng-container>\n </ng-container>\n </ng-template>\n </ng-container>\n <stream-avatar\n data-testid=\"avatar\"\n class=\"str-chat-angular__avatar-host\"\n [imageUrl]=\"message?.user?.image\"\n [name]=\"message?.user?.name || message?.user?.id\"\n ></stream-avatar>\n <div class=\"str-chat__message-inner\">\n <div\n class=\"str-chat__message-simple__actions\"\n data-testid=\"message-options\"\n *ngIf=\"areOptionsVisible\"\n >\n <div\n data-testid=\"message-actions-container\"\n class=\"\n str-chat__message-simple__actions__action\n str-chat__message-simple__actions__action--options\n \"\n [class.str-chat-angular__message-simple__actions__action--options--editing]=\"\n isEditing\n \"\n >\n <stream-message-actions-box\n [isOpen]=\"isActionBoxOpen\"\n [isMine]=\"isSentByCurrentUser\"\n [enabledActions]=\"enabledMessageActions\"\n [message]=\"message\"\n (displayedActionsCount)=\"visibleMessageActionsCount = $event\"\n (isEditing)=\"isEditing = $event; isActionBoxOpen = !isEditing\"\n [messageInputTemplate]=\"messageInputTemplate\"\n ></stream-message-actions-box>\n <stream-icon\n *ngIf=\"visibleMessageActionsCount > 0\"\n data-testid=\"action-icon\"\n icon=\"action-icon\"\n (keyup.enter)=\"isActionBoxOpen = !isActionBoxOpen\"\n (click)=\"isActionBoxOpen = !isActionBoxOpen\"\n ></stream-icon>\n </div>\n <div\n *ngIf=\"areReactionsEnabled && canReactToMessage\"\n class=\"\n str-chat__message-simple__actions__action\n str-chat__message-simple__actions__action--reactions\n \"\n data-testid=\"reaction-icon\"\n (click)=\"isReactionSelectorOpen = !isReactionSelectorOpen\"\n (keyup.enter)=\"isReactionSelectorOpen = !isReactionSelectorOpen\"\n >\n <stream-icon icon=\"reaction-icon\"></stream-icon>\n </div>\n </div>\n <stream-message-reactions\n *ngIf=\"areReactionsEnabled\"\n [messageReactionCounts]=\"message?.reaction_counts || {}\"\n [latestReactions]=\"message?.latest_reactions || []\"\n [(isSelectorOpen)]=\"isReactionSelectorOpen\"\n [messageId]=\"message?.id\"\n [ownReactions]=\"message?.own_reactions || []\"\n ></stream-message-reactions>\n <stream-attachment-list\n *ngIf=\"hasAttachment\"\n [attachments]=\"message!.attachments!\"\n ></stream-attachment-list>\n <div class=\"str-chat__message-text\" *ngIf=\"message?.text\">\n <div\n data-testid=\"inner-message\"\n class=\"\n str-chat__message-text-inner str-chat__message-simple-text-inner\n \"\n [class.str-chat__message-light-text-inner--has-attachment]=\"\n hasAttachment\n \"\n (click)=\"\n message?.status === 'failed' && message?.errorStatusCode !== 403\n ? resendMessage()\n : undefined\n \"\n (keyup.enter)=\"\n message?.status === 'failed' && message?.errorStatusCode !== 403\n ? resendMessage()\n : undefined\n \"\n >\n <div\n data-testid=\"client-error-message\"\n *ngIf=\"message?.type === 'error'\"\n class=\"str-chat__simple-message--error-message\"\n >\n {{ \"streamChat.Error \u00B7 Unsent\" | translate }}\n </div>\n <div\n data-testid=\"error-message\"\n *ngIf=\"message?.status === 'failed'\"\n class=\"str-chat__simple-message--error-message\"\n >\n {{\n (message?.errorStatusCode === 403\n ? \"streamChat.Message Failed \u00B7 Unauthorized\"\n : \"streamChat.Message Failed \u00B7 Click to try again\"\n ) | translate\n }}\n </div>\n <div\n (click)=\"textClicked()\"\n (keyup.enter)=\"textClicked()\"\n data-testid=\"text\"\n [innerHTML]=\"\n message?.html || message?.text\n | highlightMentions: message?.mentioned_users\n \"\n ></div>\n </div>\n </div>\n <div class=\"str-chat__message-data str-chat__message-simple-data\">\n <span\n data-testid=\"sender\"\n *ngIf=\"!isSentByCurrentUser\"\n class=\"str-chat__message-simple-name\"\n >\n {{ message?.user?.name ? message?.user?.name : message?.user?.id }}\n </span>\n <span data-testid=\"date\" class=\"str-chat__message-simple-timestamp\">\n {{ parsedDate }}\n </span>\n </div>\n </div>\n </ng-container>\n </ng-container>\n</div>\n\n<ng-template #sendingStatus>\n <span class=\"str-chat__message-simple-status\" data-testid=\"sending-indicator\">\n <div class=\"str-chat__tooltip\">\n {{ \"streamChat.Sending...\" | translate }}\n </div>\n <stream-loading-indicator\n data-testid=\"loading-indicator\"\n ></stream-loading-indicator>\n </span>\n</ng-template>\n<ng-template #readStatus>\n <span class=\"str-chat__message-simple-status\" data-testid=\"read-indicator\">\n <div class=\"str-chat__tooltip\" data-testid=\"read-by-tooltip\">\n {{ readByText }}\n </div>\n <stream-avatar\n class=\"str-chat-angular__avatar-host\"\n data-test-id=\"last-read-user-avatar\"\n [size]=\"15\"\n [imageUrl]=\"lastReadUser?.image\"\n [name]=\"lastReadUser?.name || lastReadUser?.id\"\n ></stream-avatar>\n <span\n data-test-id=\"read-by-length\"\n *ngIf=\"isReadByMultipleUsers\"\n class=\"str-chat__message-simple-status-number\"\n >\n {{ (message?.readBy)!.length }}\n </span>\n </span>\n</ng-template>\n<ng-template #deliveredStatus>\n <span\n class=\"str-chat__message-simple-status\"\n data-testid=\"delivered-indicator\"\n >\n <div class=\"str-chat__tooltip\">\n {{ \"streamChat.Delivered\" | translate }}\n </div>\n <stream-icon\n data-testid=\"delivered-icon\"\n icon=\"delivered-icon\"\n ></stream-icon>\n </span>\n</ng-template>\n\n<ng-template #deletedMessage>\n <div data-testid=\"message-deleted-component\">\n <div class=\"str-chat__message--deleted-inner\" translate>\n streamChat.This message was deleted...\n </div>\n </div>\n</ng-template>\n\n<ng-template #systemMessage>\n <div data-testid=\"system-message\" class=\"str-chat__message--system\">\n <div class=\"str-chat__message--system__text\">\n <div class=\"str-chat__message--system__line\"></div>\n <p>{{ message?.text }}</p>\n <div class=\"str-chat__message--system__line\"></div>\n </div>\n <div class=\"str-chat__message--system__date\">\n {{ parsedDate }}\n </div>\n </div>\n</ng-template>\n", components: [{ type: AvatarComponent, selector: "stream-avatar", inputs: ["name", "imageUrl", "size"] }, { type: MessageActionsBoxComponent, selector: "stream-message-actions-box", inputs: ["messageInputTemplate", "isOpen", "isMine", "message", "enabledActions"], outputs: ["displayedActionsCount", "isEditing"] }, { type: IconComponent, selector: "stream-icon", inputs: ["icon", "size"] }, { type: MessageReactionsComponent, selector: "stream-message-reactions", inputs: ["messageId", "messageReactionCounts", "isSelectorOpen", "latestReactions", "ownReactions"], outputs: ["isSelectorOpenChange"] }, { type: AttachmentListComponent, selector: "stream-attachment-list", inputs: ["attachments"] }, { type: LoadingIndicatorComponent, selector: "stream-loading-indicator", inputs: ["size", "color"] }], directives: [{ type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i3.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet"] }, { type: i1.TranslateDirective, selector: "[translate],[ngx-translate]", inputs: ["translate", "translateParams"] }], pipes: { "translate": i1.TranslatePipe, "highlightMentions": HighlightMentionsPipe } });
|
|
2182
2245
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: MessageComponent, decorators: [{
|
|
2183
2246
|
type: Component,
|
|
2184
2247
|
args: [{
|
|
@@ -2186,7 +2249,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImpor
|
|
|
2186
2249
|
templateUrl: './message.component.html',
|
|
2187
2250
|
styles: [],
|
|
2188
2251
|
}]
|
|
2189
|
-
}], ctorParameters: function () { return [{ type: ChatClientService }, { type: ChannelService }]; }, propDecorators: {
|
|
2252
|
+
}], ctorParameters: function () { return [{ type: ChatClientService }, { type: ChannelService }]; }, propDecorators: { messageInputTemplate: [{
|
|
2253
|
+
type: Input
|
|
2254
|
+
}], message: [{
|
|
2190
2255
|
type: Input
|
|
2191
2256
|
}], enabledMessageActions: [{
|
|
2192
2257
|
type: Input
|
|
@@ -2196,6 +2261,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImpor
|
|
|
2196
2261
|
type: Input
|
|
2197
2262
|
}], isLastSentMessage: [{
|
|
2198
2263
|
type: Input
|
|
2264
|
+
}], canReceiveReadEvents: [{
|
|
2265
|
+
type: Input
|
|
2199
2266
|
}], container: [{
|
|
2200
2267
|
type: ViewChild,
|
|
2201
2268
|
args: ['container']
|
|
@@ -2463,6 +2530,7 @@ class MessageListComponent {
|
|
|
2463
2530
|
const capabilites = (_a = channel === null || channel === void 0 ? void 0 : channel.data) === null || _a === void 0 ? void 0 : _a.own_capabilities;
|
|
2464
2531
|
if (capabilites) {
|
|
2465
2532
|
this.canReactToMessage = capabilites.indexOf('send-reaction') !== -1;
|
|
2533
|
+
this.canReceiveReadEvents = capabilites.indexOf('read-events') !== -1;
|
|
2466
2534
|
this.authorizedMessageActions = [];
|
|
2467
2535
|
if (capabilites.indexOf('flag-message') !== -1) {
|
|
2468
2536
|
this.authorizedMessageActions.push('flag');
|
|
@@ -2593,7 +2661,7 @@ class MessageListComponent {
|
|
|
2593
2661
|
}
|
|
2594
2662
|
}
|
|
2595
2663
|
MessageListComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: MessageListComponent, deps: [{ token: ChannelService }, { token: ChatClientService }, { token: ImageLoadService }], target: i0.ɵɵFactoryTarget.Component });
|
|
2596
|
-
MessageListComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.5", type: MessageListComponent, selector: "stream-message-list", inputs: { messageTemplate: "messageTemplate", areReactionsEnabled: "areReactionsEnabled", enabledMessageActionsInput: ["enabledMessageActions", "enabledMessageActionsInput"] }, host: { properties: { "class": "this.class" } }, viewQueries: [{ propertyName: "scrollContainer", first: true, predicate: ["scrollContainer"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div\n #scrollContainer\n data-testid=\"scroll-container\"\n class=\"str-chat__list\"\n (scroll)=\"scrolled()\"\n>\n <div class=\"str-chat__reverse-infinite-scroll\">\n <ul class=\"str-chat__ul\">\n <li\n data-testclass=\"message\"\n *ngFor=\"\n let message of messages$ | async;\n let i = index;\n trackBy: trackByMessageId\n \"\n class=\"str-chat__li str-chat__li--{{ groupStyles[i] }}\"\n >\n <ng-container *ngIf=\"messageTemplate; else defaultMessageTemplate\">\n <ng-container\n *ngTemplateOutlet=\"\n messageTemplate;\n context: {\n message: message,\n areReactionsEnabled: areReactionsEnabled,\n canReactToMessage: canReactToMessage,\n lastSentMessageId: !!(\n lastSentMessageId && message?.id === lastSentMessageId\n )\n }\n \"\n ></ng-container>\n </ng-container>\n <ng-template #defaultMessageTemplate>\n <stream-message\n [message]=\"message\"\n [areReactionsEnabled]=\"areReactionsEnabled\"\n [canReactToMessage]=\"canReactToMessage\"\n [isLastSentMessage]=\"\n !!(lastSentMessageId && message?.id === lastSentMessageId)\n \"\n [enabledMessageActions]=\"enabledMessageActions\"\n ></stream-message>\n </ng-template>\n </li>\n </ul>\n </div>\n</div>\n<div class=\"str-chat__list-notifications\">\n <button\n data-testid=\"scroll-to-bottom\"\n *ngIf=\"isUserScrolledUp\"\n class=\"\n str-chat__message-notification\n str-chat__message-notification-right\n str-chat__message-notification-scroll-down\n \"\n (keyup.enter)=\"scrollToBottom()\"\n (click)=\"scrollToBottom()\"\n >\n <div\n *ngIf=\"unreadMessageCount > 0\"\n class=\"\n str-chat__message-notification\n str-chat__message-notification-scroll-down-unread-count\n \"\n >\n {{ unreadMessageCount }}\n </div>\n </button>\n</div>\n", components: [{ type: MessageComponent, selector: "stream-message", inputs: ["message", "enabledMessageActions", "areReactionsEnabled", "canReactToMessage", "isLastSentMessage"] }], directives: [{ type: i3.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i3.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet"] }], pipes: { "async": i3.AsyncPipe } });
|
|
2664
|
+
MessageListComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.5", type: MessageListComponent, selector: "stream-message-list", inputs: { messageTemplate: "messageTemplate", messageInputTemplate: "messageInputTemplate", areReactionsEnabled: "areReactionsEnabled", enabledMessageActionsInput: ["enabledMessageActions", "enabledMessageActionsInput"] }, host: { properties: { "class": "this.class" } }, viewQueries: [{ propertyName: "scrollContainer", first: true, predicate: ["scrollContainer"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div\n #scrollContainer\n data-testid=\"scroll-container\"\n class=\"str-chat__list\"\n (scroll)=\"scrolled()\"\n>\n <div class=\"str-chat__reverse-infinite-scroll\">\n <ul class=\"str-chat__ul\">\n <li\n data-testclass=\"message\"\n *ngFor=\"\n let message of messages$ | async;\n let i = index;\n trackBy: trackByMessageId\n \"\n class=\"str-chat__li str-chat__li--{{ groupStyles[i] }}\"\n >\n <ng-container *ngIf=\"messageTemplate; else defaultMessageTemplate\">\n <ng-container\n *ngTemplateOutlet=\"\n messageTemplate;\n context: {\n message: message,\n areReactionsEnabled: areReactionsEnabled,\n canReactToMessage: canReactToMessage,\n lastSentMessageId: !!(\n lastSentMessageId && message?.id === lastSentMessageId\n ),\n canReceiveReadEvents: canReceiveReadEvents,\n messageInputTemplate: messageInputTemplate\n }\n \"\n ></ng-container>\n </ng-container>\n <ng-template #defaultMessageTemplate>\n <stream-message\n [message]=\"message\"\n [areReactionsEnabled]=\"areReactionsEnabled\"\n [canReactToMessage]=\"canReactToMessage\"\n [isLastSentMessage]=\"\n !!(lastSentMessageId && message?.id === lastSentMessageId)\n \"\n [enabledMessageActions]=\"enabledMessageActions\"\n [canReceiveReadEvents]=\"canReceiveReadEvents\"\n [messageInputTemplate]=\"messageInputTemplate\"\n ></stream-message>\n </ng-template>\n </li>\n </ul>\n </div>\n</div>\n<div class=\"str-chat__list-notifications\">\n <button\n data-testid=\"scroll-to-bottom\"\n *ngIf=\"isUserScrolledUp\"\n class=\"\n str-chat__message-notification\n str-chat__message-notification-right\n str-chat__message-notification-scroll-down\n \"\n (keyup.enter)=\"scrollToBottom()\"\n (click)=\"scrollToBottom()\"\n >\n <div\n *ngIf=\"unreadMessageCount > 0\"\n class=\"\n str-chat__message-notification\n str-chat__message-notification-scroll-down-unread-count\n \"\n >\n {{ unreadMessageCount }}\n </div>\n </button>\n</div>\n", components: [{ type: MessageComponent, selector: "stream-message", inputs: ["messageInputTemplate", "message", "enabledMessageActions", "areReactionsEnabled", "canReactToMessage", "isLastSentMessage", "canReceiveReadEvents"] }], directives: [{ type: i3.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i3.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet"] }], pipes: { "async": i3.AsyncPipe } });
|
|
2597
2665
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: MessageListComponent, decorators: [{
|
|
2598
2666
|
type: Component,
|
|
2599
2667
|
args: [{
|
|
@@ -2603,6 +2671,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImpor
|
|
|
2603
2671
|
}]
|
|
2604
2672
|
}], ctorParameters: function () { return [{ type: ChannelService }, { type: ChatClientService }, { type: ImageLoadService }]; }, propDecorators: { messageTemplate: [{
|
|
2605
2673
|
type: Input
|
|
2674
|
+
}], messageInputTemplate: [{
|
|
2675
|
+
type: Input
|
|
2606
2676
|
}], areReactionsEnabled: [{
|
|
2607
2677
|
type: Input
|
|
2608
2678
|
}], enabledMessageActionsInput: [{
|