stream-chat-angular 2.20.2 → 3.0.0-beta.10
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 +44 -12
- package/assets/version.d.ts +1 -1
- package/bundles/stream-chat-angular.umd.js +780 -534
- package/bundles/stream-chat-angular.umd.js.map +1 -1
- package/esm2015/assets/version.js +2 -2
- package/esm2015/lib/attachment-list/attachment-list.component.js +27 -15
- package/esm2015/lib/attachment-preview-list/attachment-preview-list.component.js +28 -22
- package/esm2015/lib/attachment.service.js +11 -5
- package/esm2015/lib/avatar-placeholder/avatar-placeholder.component.js +41 -0
- package/esm2015/lib/channel-header/channel-header.component.js +26 -12
- package/esm2015/lib/channel-list/channel-list.component.js +23 -13
- package/esm2015/lib/channel-preview/channel-preview.component.js +3 -3
- package/esm2015/lib/channel.service.js +28 -35
- package/esm2015/lib/chat-client.service.js +5 -4
- package/esm2015/lib/custom-templates.service.js +139 -0
- package/esm2015/lib/icon-placeholder/icon-placeholder.component.js +34 -0
- package/esm2015/lib/loading-indicator-placeholder/loading-indicator-placeholder.component.js +42 -0
- package/esm2015/lib/message/message.component.js +74 -29
- package/esm2015/lib/message-actions-box/message-actions-box.component.js +114 -99
- package/esm2015/lib/message-input/autocomplete-textarea/autocomplete-textarea.component.js +13 -13
- package/esm2015/lib/message-input/message-input-config.service.js +1 -1
- package/esm2015/lib/message-input/message-input.component.js +56 -45
- package/esm2015/lib/message-input/textarea.directive.js +2 -18
- package/esm2015/lib/message-input/textarea.interface.js +1 -1
- package/esm2015/lib/message-list/message-list.component.js +32 -93
- package/esm2015/lib/message-preview.js +4 -17
- package/esm2015/lib/message-reactions/message-reactions.component.js +3 -3
- package/esm2015/lib/modal/modal.component.js +9 -6
- package/esm2015/lib/notification/notification.component.js +5 -2
- package/esm2015/lib/notification-list/notification-list.component.js +12 -10
- package/esm2015/lib/read-by.js +1 -1
- package/esm2015/lib/stream-avatar.module.js +5 -4
- package/esm2015/lib/stream-chat.module.js +13 -3
- package/esm2015/lib/thread/thread.component.js +19 -11
- package/esm2015/lib/types.js +1 -1
- package/esm2015/public-api.js +5 -1
- package/fesm2015/stream-chat-angular.js +723 -449
- package/fesm2015/stream-chat-angular.js.map +1 -1
- package/lib/attachment-list/attachment-list.component.d.ts +12 -8
- package/lib/attachment-preview-list/attachment-preview-list.component.d.ts +17 -7
- package/lib/attachment.service.d.ts +1 -1
- package/lib/avatar-placeholder/avatar-placeholder.component.d.ts +25 -0
- package/lib/channel-header/channel-header.component.d.ts +15 -12
- package/lib/channel-list/channel-list.component.d.ts +14 -11
- package/lib/channel-preview/channel-preview.component.d.ts +3 -2
- package/lib/channel.service.d.ts +32 -31
- package/lib/chat-client.service.d.ts +12 -11
- package/lib/custom-templates.service.d.ts +132 -0
- package/lib/icon-placeholder/icon-placeholder.component.d.ts +22 -0
- package/lib/loading-indicator-placeholder/loading-indicator-placeholder.component.d.ts +21 -0
- package/lib/message/message.component.d.ts +42 -30
- package/lib/message-actions-box/message-actions-box.component.d.ts +22 -26
- package/lib/message-input/autocomplete-textarea/autocomplete-textarea.component.d.ts +7 -11
- package/lib/message-input/message-input-config.service.d.ts +0 -19
- package/lib/message-input/message-input.component.d.ts +40 -26
- package/lib/message-input/textarea.directive.d.ts +3 -6
- package/lib/message-input/textarea.interface.d.ts +1 -4
- package/lib/message-list/group-styles.d.ts +1 -1
- package/lib/message-list/message-list.component.d.ts +10 -34
- package/lib/message-preview.d.ts +2 -1
- package/lib/message-reactions/message-reactions.component.d.ts +4 -5
- package/lib/modal/modal.component.d.ts +7 -3
- package/lib/notification/notification.component.d.ts +6 -1
- package/lib/notification-list/notification-list.component.d.ts +4 -2
- package/lib/read-by.d.ts +2 -1
- package/lib/stream-avatar.module.d.ts +4 -3
- package/lib/stream-chat.module.d.ts +6 -4
- package/lib/thread/thread.component.d.ts +6 -3
- package/lib/types.d.ts +115 -9
- package/package.json +2 -3
- package/public-api.d.ts +4 -0
- package/src/assets/styles/assets/EmojiOneColor.woff2 +0 -0
- package/src/assets/styles/assets/NotoColorEmoji-flags.woff2 +0 -0
- package/src/assets/styles/assets/Poweredby_100px-White_VertText.png +0 -0
- package/src/assets/styles/assets/str-chat__reaction-list-sprite@1x.png +0 -0
- package/src/assets/styles/assets/str-chat__reaction-list-sprite@2x.png +0 -0
- package/src/assets/styles/assets/str-chat__reaction-list-sprite@3x.png +0 -0
- package/src/assets/styles/css/index.css +1 -0
- package/src/assets/styles/css/index.css.map +1 -0
- package/src/assets/styles/scss/ActionsBox.scss +56 -0
- package/src/assets/styles/scss/Attachment.scss +227 -0
- package/src/assets/styles/scss/AttachmentActions.scss +44 -0
- package/src/assets/styles/scss/Audio.scss +112 -0
- package/src/assets/styles/scss/Avatar.scss +79 -0
- package/src/assets/styles/scss/Card.scss +100 -0
- package/src/assets/styles/scss/ChannelHeader.scss +284 -0
- package/src/assets/styles/scss/ChannelList.scss +117 -0
- package/src/assets/styles/scss/ChannelListMessenger.scss +9 -0
- package/src/assets/styles/scss/ChannelPreview.scss +108 -0
- package/src/assets/styles/scss/ChannelSearch.scss +111 -0
- package/src/assets/styles/scss/ChatDown.scss +15 -0
- package/src/assets/styles/scss/DateSeparator.scss +51 -0
- package/src/assets/styles/scss/EditMessageForm.scss +112 -0
- package/src/assets/styles/scss/EventComponent.scss +48 -0
- package/src/assets/styles/scss/Gallery.scss +135 -0
- package/src/assets/styles/scss/InfiniteScrollPaginator.scss +6 -0
- package/src/assets/styles/scss/LoadMoreButton.scss +44 -0
- package/src/assets/styles/scss/LoadingChannels.scss +70 -0
- package/src/assets/styles/scss/LoadingIndicator.scss +38 -0
- package/src/assets/styles/scss/Message.scss +1261 -0
- package/src/assets/styles/scss/MessageActions.scss +112 -0
- package/src/assets/styles/scss/MessageCommerce.scss +564 -0
- package/src/assets/styles/scss/MessageInput.scss +385 -0
- package/src/assets/styles/scss/MessageInputFlat.scss +305 -0
- package/src/assets/styles/scss/MessageList.scss +203 -0
- package/src/assets/styles/scss/MessageLivestream.scss +325 -0
- package/src/assets/styles/scss/MessageNotification.scss +49 -0
- package/src/assets/styles/scss/MessageRepliesCountButton.scss +33 -0
- package/src/assets/styles/scss/MessageTeam.scss +617 -0
- package/src/assets/styles/scss/Modal.scss +77 -0
- package/src/assets/styles/scss/ReactionList.scss +183 -0
- package/src/assets/styles/scss/ReactionSelector.scss +212 -0
- package/src/assets/styles/scss/SendButton.scss +14 -0
- package/src/assets/styles/scss/SimpleReactionsList.scss +76 -0
- package/src/assets/styles/scss/SmallMessageInput.scss +172 -0
- package/src/assets/styles/scss/Thread.scss +306 -0
- package/src/assets/styles/scss/Tooltip.scss +38 -0
- package/src/assets/styles/scss/TypingIndicator.scss +75 -0
- package/src/assets/styles/scss/VirtualMessage.scss +291 -0
- package/src/assets/styles/scss/_base.scss +206 -0
- package/src/assets/styles/scss/_variables.scss +158 -0
- package/src/assets/styles/scss/index.scss +50 -0
- package/src/assets/styles/scss/vendor/emoji-mart.scss +495 -0
- package/src/assets/styles/scss/vendor/mml-react.scss +1749 -0
- package/src/assets/styles/scss/vendor/react-file-utils.scss +378 -0
- package/src/assets/styles/scss/vendor/react-image-gallery.scss +224 -0
- package/src/assets/version.ts +1 -1
|
@@ -1,23 +1,23 @@
|
|
|
1
1
|
import { __awaiter } from 'tslib';
|
|
2
2
|
import * as i0 from '@angular/core';
|
|
3
|
-
import { Injectable, Component, Input,
|
|
3
|
+
import { Injectable, Component, Input, EventEmitter, Output, ViewChild, InjectionToken, Directive, Inject, HostBinding, NgModule } from '@angular/core';
|
|
4
4
|
import { BehaviorSubject, ReplaySubject, combineLatest, Subject, timer, of } from 'rxjs';
|
|
5
5
|
import { StreamChat } from 'stream-chat';
|
|
6
6
|
import { map, shareReplay, filter, first, take, tap, catchError, startWith, distinctUntilChanged, debounceTime } from 'rxjs/operators';
|
|
7
7
|
import { v4 } from 'uuid';
|
|
8
8
|
import * as i2 from '@ngx-translate/core';
|
|
9
9
|
import { TranslateModule } from '@ngx-translate/core';
|
|
10
|
-
import * as
|
|
10
|
+
import * as i3 from '@angular/common';
|
|
11
11
|
import { CommonModule } from '@angular/common';
|
|
12
12
|
import prettybytes from 'pretty-bytes';
|
|
13
13
|
import Dayjs from 'dayjs';
|
|
14
14
|
import calendar from 'dayjs/plugin/calendar';
|
|
15
15
|
import emojiRegex from 'emoji-regex';
|
|
16
16
|
import transliterate from '@stream-io/transliterate';
|
|
17
|
-
import * as
|
|
17
|
+
import * as i7 from 'angular-mentions';
|
|
18
18
|
import { MentionModule } from 'angular-mentions';
|
|
19
19
|
|
|
20
|
-
const version = '
|
|
20
|
+
const version = '3.0.0-beta.10';
|
|
21
21
|
|
|
22
22
|
/**
|
|
23
23
|
* The `NotificationService` can be used to add or remove notifications. By default the [`NotificationList`](../components/NotificationListComponent.mdx) component displays the currently active notifications.
|
|
@@ -106,7 +106,7 @@ class ChatClientService {
|
|
|
106
106
|
this.connectionStateSubject = new ReplaySubject(1);
|
|
107
107
|
this.appSettingsSubject = new BehaviorSubject(undefined);
|
|
108
108
|
this.pendingInvitesSubject = new BehaviorSubject([]);
|
|
109
|
-
this.
|
|
109
|
+
this.events$ = this.notificationSubject.asObservable();
|
|
110
110
|
this.connectionState$ = this.connectionStateSubject.asObservable();
|
|
111
111
|
this.appSettings$ = this.appSettingsSubject.asObservable();
|
|
112
112
|
this.pendingInvites$ = this.pendingInvitesSubject.asObservable();
|
|
@@ -127,7 +127,8 @@ class ChatClientService {
|
|
|
127
127
|
yield this.chatClient.connectUser(user, userTokenOrProvider);
|
|
128
128
|
this.chatClient.setUserAgent(`stream-chat-angular-${version}-${this.chatClient.getUserAgent()}`);
|
|
129
129
|
}));
|
|
130
|
-
const channels = yield this.chatClient.queryChannels({ invite: 'pending' },
|
|
130
|
+
const channels = yield this.chatClient.queryChannels({ invite: 'pending' }, // TODO: find out why we need this typecast
|
|
131
|
+
{}, { user_id: (_a = this.chatClient.user) === null || _a === void 0 ? void 0 : _a.id });
|
|
131
132
|
this.pendingInvitesSubject.next(channels);
|
|
132
133
|
this.appSettingsSubject.next(undefined);
|
|
133
134
|
this.chatClient.on((e) => {
|
|
@@ -201,7 +202,7 @@ class ChatClientService {
|
|
|
201
202
|
{ name: { $autocomplete: searchTerm } },
|
|
202
203
|
],
|
|
203
204
|
id: { $ne: this.chatClient.userID },
|
|
204
|
-
});
|
|
205
|
+
}); // TODO: find out why we need this typecast
|
|
205
206
|
return result.users;
|
|
206
207
|
});
|
|
207
208
|
}
|
|
@@ -232,23 +233,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImpor
|
|
|
232
233
|
}]
|
|
233
234
|
}], ctorParameters: function () { return [{ type: i0.NgZone }, { type: NotificationService }]; } });
|
|
234
235
|
|
|
235
|
-
const createMessagePreview = (user, text, attachments = [], mentionedUsers = [], parentId = undefined, quotedMessageId = undefined) => {
|
|
236
|
+
const createMessagePreview = (user, text, attachments = [], mentionedUsers = [], parentId = undefined, quotedMessageId = undefined, customData) => {
|
|
236
237
|
const clientSideId = `${user.id}-${v4()}`;
|
|
237
|
-
return {
|
|
238
|
-
|
|
239
|
-
created_at: new Date(),
|
|
240
|
-
html: text,
|
|
241
|
-
id: clientSideId,
|
|
242
|
-
reactions: [],
|
|
243
|
-
status: 'sending',
|
|
244
|
-
text,
|
|
245
|
-
type: 'regular',
|
|
246
|
-
user,
|
|
247
|
-
attachments,
|
|
248
|
-
mentioned_users: mentionedUsers,
|
|
249
|
-
parent_id: parentId,
|
|
250
|
-
quoted_message_id: quotedMessageId,
|
|
251
|
-
};
|
|
238
|
+
return Object.assign({ __html: text, created_at: new Date(), html: text, id: clientSideId, reactions: [], status: 'sending', text, type: 'regular', user,
|
|
239
|
+
attachments, mentioned_users: mentionedUsers, parent_id: parentId, quoted_message_id: quotedMessageId }, customData);
|
|
252
240
|
};
|
|
253
241
|
|
|
254
242
|
const getReadBy = (message, channel) => {
|
|
@@ -442,7 +430,7 @@ class ChannelService {
|
|
|
442
430
|
};
|
|
443
431
|
this.sort = sort || { last_message_at: -1, updated_at: -1 };
|
|
444
432
|
yield this.queryChannels();
|
|
445
|
-
this.chatClientService.
|
|
433
|
+
this.chatClientService.events$.subscribe((notification) => void this.handleNotification(notification));
|
|
446
434
|
});
|
|
447
435
|
}
|
|
448
436
|
/**
|
|
@@ -470,13 +458,12 @@ class ChannelService {
|
|
|
470
458
|
* Adds a reaction to a message.
|
|
471
459
|
* @param messageId The id of the message to add the reaction to
|
|
472
460
|
* @param reactionType The type of the reaction
|
|
461
|
+
* @param customData
|
|
473
462
|
*/
|
|
474
|
-
addReaction(messageId, reactionType) {
|
|
463
|
+
addReaction(messageId, reactionType, customData) {
|
|
475
464
|
var _a;
|
|
476
465
|
return __awaiter(this, void 0, void 0, function* () {
|
|
477
|
-
yield ((_a = this.activeChannelSubject.getValue()) === null || _a === void 0 ? void 0 : _a.sendReaction(messageId, {
|
|
478
|
-
type: reactionType,
|
|
479
|
-
}));
|
|
466
|
+
yield ((_a = this.activeChannelSubject.getValue()) === null || _a === void 0 ? void 0 : _a.sendReaction(messageId, Object.assign({ type: reactionType }, customData)));
|
|
480
467
|
});
|
|
481
468
|
}
|
|
482
469
|
/**
|
|
@@ -498,14 +485,15 @@ class ChannelService {
|
|
|
498
485
|
* @param mentionedUsers Mentioned users
|
|
499
486
|
* @param parentId Id of the parent message (if sending a thread reply)
|
|
500
487
|
* @param quotedMessageId Id of the message to quote (if sending a quote reply)
|
|
488
|
+
* @param customData
|
|
501
489
|
*/
|
|
502
|
-
sendMessage(text, attachments = [], mentionedUsers = [], parentId = undefined, quotedMessageId = undefined) {
|
|
490
|
+
sendMessage(text, attachments = [], mentionedUsers = [], parentId = undefined, quotedMessageId = undefined, customData = undefined) {
|
|
503
491
|
return __awaiter(this, void 0, void 0, function* () {
|
|
504
|
-
const preview = createMessagePreview(this.chatClientService.chatClient.user, text, attachments, mentionedUsers, parentId, quotedMessageId);
|
|
492
|
+
const preview = createMessagePreview(this.chatClientService.chatClient.user, text, attachments, mentionedUsers, parentId, quotedMessageId, customData);
|
|
505
493
|
const channel = this.activeChannelSubject.getValue();
|
|
506
494
|
preview.readBy = [];
|
|
507
495
|
channel.state.addMessageSorted(preview, true);
|
|
508
|
-
yield this.sendMessageRequest(preview);
|
|
496
|
+
yield this.sendMessageRequest(preview, customData);
|
|
509
497
|
});
|
|
510
498
|
}
|
|
511
499
|
/**
|
|
@@ -600,7 +588,7 @@ class ChannelService {
|
|
|
600
588
|
const result = yield activeChannel.queryMembers({
|
|
601
589
|
name: { $autocomplete: searchTerm },
|
|
602
590
|
id: { $ne: this.chatClientService.chatClient.userID },
|
|
603
|
-
});
|
|
591
|
+
}); // TODO: find out why we need typecast here
|
|
604
592
|
return Object.values(result.members);
|
|
605
593
|
}
|
|
606
594
|
});
|
|
@@ -645,7 +633,7 @@ class ChannelService {
|
|
|
645
633
|
selectMessageToQuote(message) {
|
|
646
634
|
this.messageToQuoteSubject.next(message);
|
|
647
635
|
}
|
|
648
|
-
sendMessageRequest(preview) {
|
|
636
|
+
sendMessageRequest(preview, customData) {
|
|
649
637
|
var _a;
|
|
650
638
|
return __awaiter(this, void 0, void 0, function* () {
|
|
651
639
|
const channel = this.activeChannelSubject.getValue();
|
|
@@ -656,14 +644,7 @@ class ChannelService {
|
|
|
656
644
|
])
|
|
657
645
|
: this.activeChannelMessagesSubject.next([...channel.state.messages]);
|
|
658
646
|
try {
|
|
659
|
-
const response = yield channel.sendMessage({
|
|
660
|
-
text: preview.text,
|
|
661
|
-
attachments: preview.attachments,
|
|
662
|
-
mentioned_users: (_a = preview.mentioned_users) === null || _a === void 0 ? void 0 : _a.map((u) => u.id),
|
|
663
|
-
id: preview.id,
|
|
664
|
-
parent_id: preview.parent_id,
|
|
665
|
-
quoted_message_id: preview.quoted_message_id,
|
|
666
|
-
});
|
|
647
|
+
const response = yield channel.sendMessage(Object.assign({ id: preview.id, text: preview.text, attachments: preview.attachments, mentioned_users: (_a = preview.mentioned_users) === null || _a === void 0 ? void 0 : _a.map((u) => u.id), parent_id: preview.parent_id, quoted_message_id: preview.quoted_message_id }, customData)); // TODO: find out why we need typecast here
|
|
667
648
|
if (response === null || response === void 0 ? void 0 : response.message) {
|
|
668
649
|
channel.state.addMessageSorted(Object.assign(Object.assign({}, response.message), { status: 'received' }), true);
|
|
669
650
|
isThreadReply
|
|
@@ -687,15 +668,15 @@ class ChannelService {
|
|
|
687
668
|
}
|
|
688
669
|
});
|
|
689
670
|
}
|
|
690
|
-
handleNotification(
|
|
691
|
-
switch (
|
|
671
|
+
handleNotification(clientEvent) {
|
|
672
|
+
switch (clientEvent.eventType) {
|
|
692
673
|
case 'notification.message_new': {
|
|
693
674
|
this.ngZone.run(() => {
|
|
694
675
|
if (this.customNewMessageNotificationHandler) {
|
|
695
|
-
this.customNewMessageNotificationHandler(
|
|
676
|
+
this.customNewMessageNotificationHandler(clientEvent, this.channelListSetter);
|
|
696
677
|
}
|
|
697
678
|
else {
|
|
698
|
-
this.handleNewMessageNotification(
|
|
679
|
+
this.handleNewMessageNotification(clientEvent);
|
|
699
680
|
}
|
|
700
681
|
});
|
|
701
682
|
break;
|
|
@@ -703,10 +684,10 @@ class ChannelService {
|
|
|
703
684
|
case 'notification.added_to_channel': {
|
|
704
685
|
this.ngZone.run(() => {
|
|
705
686
|
if (this.customAddedToChannelNotificationHandler) {
|
|
706
|
-
this.customAddedToChannelNotificationHandler(
|
|
687
|
+
this.customAddedToChannelNotificationHandler(clientEvent, this.channelListSetter);
|
|
707
688
|
}
|
|
708
689
|
else {
|
|
709
|
-
this.handleAddedToChannelNotification(
|
|
690
|
+
this.handleAddedToChannelNotification(clientEvent);
|
|
710
691
|
}
|
|
711
692
|
});
|
|
712
693
|
break;
|
|
@@ -714,27 +695,27 @@ class ChannelService {
|
|
|
714
695
|
case 'notification.removed_from_channel': {
|
|
715
696
|
this.ngZone.run(() => {
|
|
716
697
|
if (this.customRemovedFromChannelNotificationHandler) {
|
|
717
|
-
this.customRemovedFromChannelNotificationHandler(
|
|
698
|
+
this.customRemovedFromChannelNotificationHandler(clientEvent, this.channelListSetter);
|
|
718
699
|
}
|
|
719
700
|
else {
|
|
720
|
-
this.handleRemovedFromChannelNotification(
|
|
701
|
+
this.handleRemovedFromChannelNotification(clientEvent);
|
|
721
702
|
}
|
|
722
703
|
});
|
|
723
704
|
}
|
|
724
705
|
}
|
|
725
706
|
}
|
|
726
|
-
handleRemovedFromChannelNotification(
|
|
727
|
-
const channelIdToBeRemoved =
|
|
707
|
+
handleRemovedFromChannelNotification(clientEvent) {
|
|
708
|
+
const channelIdToBeRemoved = clientEvent.event.channel.cid;
|
|
728
709
|
this.removeChannelsFromChannelList([channelIdToBeRemoved]);
|
|
729
710
|
}
|
|
730
|
-
handleNewMessageNotification(
|
|
731
|
-
if (
|
|
732
|
-
this.addChannelsFromNotification([
|
|
711
|
+
handleNewMessageNotification(clientEvent) {
|
|
712
|
+
if (clientEvent.event.channel) {
|
|
713
|
+
this.addChannelsFromNotification([clientEvent.event.channel]);
|
|
733
714
|
}
|
|
734
715
|
}
|
|
735
|
-
handleAddedToChannelNotification(
|
|
736
|
-
if (
|
|
737
|
-
this.addChannelsFromNotification([
|
|
716
|
+
handleAddedToChannelNotification(clientEvent) {
|
|
717
|
+
if (clientEvent.event.channel) {
|
|
718
|
+
this.addChannelsFromNotification([clientEvent.event.channel]);
|
|
738
719
|
}
|
|
739
720
|
}
|
|
740
721
|
addChannelsFromNotification(channelResponses) {
|
|
@@ -1315,19 +1296,25 @@ class AttachmentService {
|
|
|
1315
1296
|
deleteAttachment(upload) {
|
|
1316
1297
|
return __awaiter(this, void 0, void 0, function* () {
|
|
1317
1298
|
const attachmentUploads = this.attachmentUploadsSubject.getValue();
|
|
1299
|
+
let result;
|
|
1318
1300
|
if (upload.state === 'success') {
|
|
1319
1301
|
try {
|
|
1320
1302
|
yield this.channelService.deleteAttachment(upload);
|
|
1321
|
-
attachmentUploads
|
|
1303
|
+
result = [...attachmentUploads];
|
|
1304
|
+
const index = attachmentUploads.indexOf(upload);
|
|
1305
|
+
result.splice(index, 1);
|
|
1322
1306
|
}
|
|
1323
1307
|
catch (error) {
|
|
1308
|
+
result = attachmentUploads;
|
|
1324
1309
|
this.notificationService.addTemporaryNotification('streamChat.Error deleting attachment');
|
|
1325
1310
|
}
|
|
1326
1311
|
}
|
|
1327
1312
|
else {
|
|
1328
|
-
attachmentUploads
|
|
1313
|
+
result = [...attachmentUploads];
|
|
1314
|
+
const index = attachmentUploads.indexOf(upload);
|
|
1315
|
+
result.splice(index, 1);
|
|
1329
1316
|
}
|
|
1330
|
-
this.attachmentUploadsSubject.next([...
|
|
1317
|
+
this.attachmentUploadsSubject.next([...result]);
|
|
1331
1318
|
});
|
|
1332
1319
|
}
|
|
1333
1320
|
/**
|
|
@@ -1409,9 +1396,9 @@ class AttachmentService {
|
|
|
1409
1396
|
}
|
|
1410
1397
|
uploadAttachments(uploads) {
|
|
1411
1398
|
return __awaiter(this, void 0, void 0, function* () {
|
|
1412
|
-
const attachmentUploads = this.attachmentUploadsSubject.getValue();
|
|
1413
1399
|
this.attachmentUploadInProgressCounterSubject.next(this.attachmentUploadInProgressCounterSubject.getValue() + 1);
|
|
1414
1400
|
const result = yield this.channelService.uploadAttachments(uploads);
|
|
1401
|
+
const attachmentUploads = this.attachmentUploadsSubject.getValue();
|
|
1415
1402
|
result.forEach((r) => {
|
|
1416
1403
|
const upload = attachmentUploads.find((upload) => upload.file === r.file);
|
|
1417
1404
|
if (!upload) {
|
|
@@ -1575,7 +1562,7 @@ class AvatarComponent {
|
|
|
1575
1562
|
}
|
|
1576
1563
|
}
|
|
1577
1564
|
AvatarComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: AvatarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1578
|
-
AvatarComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.5", type: AvatarComponent, selector: "stream-avatar", inputs: { name: "name", imageUrl: "imageUrl", size: "size" }, ngImport: i0, template: "<div\n class=\"str-chat__avatar str-chat__avatar--circle\"\n title=\"{{ name }}\"\n [style]=\"{\n flexBasis: size + 'px',\n fontSize: size / 2 + 'px',\n height: size + 'px',\n lineHeight: size + 'px',\n width: size + 'px'\n }\"\n>\n <img\n *ngIf=\"imageUrl && !isError; else fallback\"\n class=\"str-chat__avatar-image str-chat__avatar-image{{\n isLoaded ? ' str-chat__avatar-image--loaded' : ''\n }}\"\n src=\"{{ imageUrl }}\"\n alt=\"{{ initials }}\"\n data-testid=\"avatar-img\"\n (load)=\"isLoaded = true\"\n (error)=\"isError = true\"\n [style]=\"{\n flexBasis: size + 'px',\n height: size + 'px',\n objectFit: 'cover',\n width: size + 'px'\n }\"\n />\n <ng-template #fallback>\n <div data-testid=\"fallback-img\" class=\"str-chat__avatar-fallback\">\n {{ initials }}\n </div>\n </ng-template>\n</div>\n", styles: [""], directives: [{ type:
|
|
1565
|
+
AvatarComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.5", type: AvatarComponent, selector: "stream-avatar", inputs: { name: "name", imageUrl: "imageUrl", size: "size" }, ngImport: i0, template: "<div\n class=\"str-chat__avatar str-chat__avatar--circle\"\n title=\"{{ name }}\"\n [style]=\"{\n flexBasis: size + 'px',\n fontSize: size / 2 + 'px',\n height: size + 'px',\n lineHeight: size + 'px',\n width: size + 'px'\n }\"\n>\n <img\n *ngIf=\"imageUrl && !isError; else fallback\"\n class=\"str-chat__avatar-image str-chat__avatar-image{{\n isLoaded ? ' str-chat__avatar-image--loaded' : ''\n }}\"\n src=\"{{ imageUrl }}\"\n alt=\"{{ initials }}\"\n data-testid=\"avatar-img\"\n (load)=\"isLoaded = true\"\n (error)=\"isError = true\"\n [style]=\"{\n flexBasis: size + 'px',\n height: size + 'px',\n objectFit: 'cover',\n width: size + 'px'\n }\"\n />\n <ng-template #fallback>\n <div data-testid=\"fallback-img\" class=\"str-chat__avatar-fallback\">\n {{ initials }}\n </div>\n </ng-template>\n</div>\n", styles: [""], directives: [{ type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }] });
|
|
1579
1566
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: AvatarComponent, decorators: [{
|
|
1580
1567
|
type: Component,
|
|
1581
1568
|
args: [{
|
|
@@ -1591,6 +1578,178 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImpor
|
|
|
1591
1578
|
type: Input
|
|
1592
1579
|
}] } });
|
|
1593
1580
|
|
|
1581
|
+
/**
|
|
1582
|
+
* A central location for registering your custom templates to override parts of the chat application.
|
|
1583
|
+
*
|
|
1584
|
+
* For code examples to the different customizations see our [customizations example application](https://github.com/GetStream/stream-chat-angular/tree/master/projects/customizations-example), specifically the [AppComponent](https://github.com/GetStream/stream-chat-angular/tree/master/projects/customizations-example/src/app) (see [README](https://github.com/GetStream/stream-chat-angular/blob/master/README.md#customization-examples) for instructions on how to start the application).
|
|
1585
|
+
*/
|
|
1586
|
+
class CustomTemplatesService {
|
|
1587
|
+
constructor() {
|
|
1588
|
+
/**
|
|
1589
|
+
* The autocomplete list item template for mentioning users (used in the [`AutocompleteTextareaComponent`](../components/AutocompleteTextareaComponent.mdx))
|
|
1590
|
+
*/
|
|
1591
|
+
this.mentionAutocompleteItemTemplate$ = new BehaviorSubject(undefined);
|
|
1592
|
+
/**
|
|
1593
|
+
* The autocomplete list item template for commands (used in the [`AutocompleteTextareaComponent`](../components/AutocompleteTextareaComponent.mdx))
|
|
1594
|
+
*
|
|
1595
|
+
* For code examples to the different customizations see our [customizations example application](https://github.com/GetStream/stream-chat-angular/tree/master/projects/customizations-example), specifically the [AppComponent](https://github.com/GetStream/stream-chat-angular/tree/master/projects/customizations-example/src/app) (see [README](https://github.com/GetStream/stream-chat-angular/blob/master/README.md#customization-examples) for instructions on how to start the application).
|
|
1596
|
+
*/
|
|
1597
|
+
this.commandAutocompleteItemTemplate$ = new BehaviorSubject(undefined);
|
|
1598
|
+
/**
|
|
1599
|
+
* Template used to display an item in the [channel list](../components/ChannelListComponent.mdx) (instead of the default [channal list item](../components/ChannelPreviewComponent.mdx))
|
|
1600
|
+
*
|
|
1601
|
+
* For code examples to the different customizations see our [customizations example application](https://github.com/GetStream/stream-chat-angular/tree/master/projects/customizations-example), specifically the [AppComponent](https://github.com/GetStream/stream-chat-angular/tree/master/projects/customizations-example/src/app) (see [README](https://github.com/GetStream/stream-chat-angular/blob/master/README.md#customization-examples) for instructions on how to start the application).
|
|
1602
|
+
*/
|
|
1603
|
+
this.channelPreviewTemplate$ = new BehaviorSubject(undefined);
|
|
1604
|
+
/**
|
|
1605
|
+
* The message input template used when editing a message (instead of the [default message input](../components/MessageInputComponent.mdx))
|
|
1606
|
+
*
|
|
1607
|
+
* For code examples to the different customizations see our [customizations example application](https://github.com/GetStream/stream-chat-angular/tree/master/projects/customizations-example), specifically the [AppComponent](https://github.com/GetStream/stream-chat-angular/tree/master/projects/customizations-example/src/app) (see [README](https://github.com/GetStream/stream-chat-angular/blob/master/README.md#customization-examples) for instructions on how to start the application).
|
|
1608
|
+
*/
|
|
1609
|
+
this.messageInputTemplate$ = new BehaviorSubject(undefined);
|
|
1610
|
+
/**
|
|
1611
|
+
* The template used for displaying a [mention inside a message](../code-examples/mention-actions.mdx)
|
|
1612
|
+
*
|
|
1613
|
+
* For code examples to the different customizations see our [customizations example application](https://github.com/GetStream/stream-chat-angular/tree/master/projects/customizations-example), specifically the [AppComponent](https://github.com/GetStream/stream-chat-angular/tree/master/projects/customizations-example/src/app) (see [README](https://github.com/GetStream/stream-chat-angular/blob/master/README.md#customization-examples) for instructions on how to start the application).
|
|
1614
|
+
*/
|
|
1615
|
+
this.mentionTemplate$ = new BehaviorSubject(undefined);
|
|
1616
|
+
/**
|
|
1617
|
+
* The template for [emoji picker](../code-examples/emoji-picker.mdx)
|
|
1618
|
+
*
|
|
1619
|
+
* For code examples to the different customizations see our [customizations example application](https://github.com/GetStream/stream-chat-angular/tree/master/projects/customizations-example), specifically the [AppComponent](https://github.com/GetStream/stream-chat-angular/tree/master/projects/customizations-example/src/app) (see [README](https://github.com/GetStream/stream-chat-angular/blob/master/README.md#customization-examples) for instructions on how to start the application).
|
|
1620
|
+
*/
|
|
1621
|
+
this.emojiPickerTemplate$ = new BehaviorSubject(undefined);
|
|
1622
|
+
/**
|
|
1623
|
+
* The typing indicator template used in the [message list](../components/MessageListComponent.mdx)
|
|
1624
|
+
*
|
|
1625
|
+
* For code examples to the different customizations see our [customizations example application](https://github.com/GetStream/stream-chat-angular/tree/master/projects/customizations-example), specifically the [AppComponent](https://github.com/GetStream/stream-chat-angular/tree/master/projects/customizations-example/src/app) (see [README](https://github.com/GetStream/stream-chat-angular/blob/master/README.md#customization-examples) for instructions on how to start the application).
|
|
1626
|
+
*/
|
|
1627
|
+
this.typingIndicatorTemplate$ = new BehaviorSubject(undefined);
|
|
1628
|
+
/**
|
|
1629
|
+
* The template used to display a message in the [message list](../components/MessageListComponent.mdx) (instead of the [default message component](../components/MessageComponent.mdx))
|
|
1630
|
+
*
|
|
1631
|
+
* For code examples to the different customizations see our [customizations example application](https://github.com/GetStream/stream-chat-angular/tree/master/projects/customizations-example), specifically the [AppComponent](https://github.com/GetStream/stream-chat-angular/tree/master/projects/customizations-example/src/app) (see [README](https://github.com/GetStream/stream-chat-angular/blob/master/README.md#customization-examples) for instructions on how to start the application).
|
|
1632
|
+
*/
|
|
1633
|
+
this.messageTemplate$ = new BehaviorSubject(undefined);
|
|
1634
|
+
/**
|
|
1635
|
+
* The template for channel actions displayed in the [channel header](../components/ChannelHeaderComponent.mdx) (by default no channel action is displayed)
|
|
1636
|
+
*
|
|
1637
|
+
* For code examples to the different customizations see our [customizations example application](https://github.com/GetStream/stream-chat-angular/tree/master/projects/customizations-example), specifically the [AppComponent](https://github.com/GetStream/stream-chat-angular/tree/master/projects/customizations-example/src/app) (see [README](https://github.com/GetStream/stream-chat-angular/blob/master/README.md#customization-examples) for instructions on how to start the application).
|
|
1638
|
+
*/
|
|
1639
|
+
this.channelActionsTemplate$ = new BehaviorSubject(undefined);
|
|
1640
|
+
/**
|
|
1641
|
+
* The template used to display attachments of a [message](../components/MessageComponent.mdx) (instead of the [default attachment list](../components/AttachmentListComponent.mdx))
|
|
1642
|
+
*
|
|
1643
|
+
* For code examples to the different customizations see our [customizations example application](https://github.com/GetStream/stream-chat-angular/tree/master/projects/customizations-example), specifically the [AppComponent](https://github.com/GetStream/stream-chat-angular/tree/master/projects/customizations-example/src/app) (see [README](https://github.com/GetStream/stream-chat-angular/blob/master/README.md#customization-examples) for instructions on how to start the application).
|
|
1644
|
+
*/
|
|
1645
|
+
this.attachmentListTemplate$ = new BehaviorSubject(undefined);
|
|
1646
|
+
/**
|
|
1647
|
+
* The template used to display attachments in the [message input](../components/MessageInputComponent.mdx) component (instead of the [default attachment preview](../components/AttachmentPreviewListComponent.mdx))
|
|
1648
|
+
*
|
|
1649
|
+
* For code examples to the different customizations see our [customizations example application](https://github.com/GetStream/stream-chat-angular/tree/master/projects/customizations-example), specifically the [AppComponent](https://github.com/GetStream/stream-chat-angular/tree/master/projects/customizations-example/src/app) (see [README](https://github.com/GetStream/stream-chat-angular/blob/master/README.md#customization-examples) for instructions on how to start the application).
|
|
1650
|
+
*/
|
|
1651
|
+
this.attachmentPreviewListTemplate$ = new BehaviorSubject(undefined);
|
|
1652
|
+
/**
|
|
1653
|
+
* The template used to display avatars for channels and users (instead of the [default avatar](../components/AvatarComponent.mdx))
|
|
1654
|
+
*
|
|
1655
|
+
* For code examples to the different customizations see our [customizations example application](https://github.com/GetStream/stream-chat-angular/tree/master/projects/customizations-example), specifically the [AppComponent](https://github.com/GetStream/stream-chat-angular/tree/master/projects/customizations-example/src/app) (see [README](https://github.com/GetStream/stream-chat-angular/blob/master/README.md#customization-examples) for instructions on how to start the application).
|
|
1656
|
+
*/
|
|
1657
|
+
this.avatarTemplate$ = new BehaviorSubject(undefined);
|
|
1658
|
+
/**
|
|
1659
|
+
* Template for displaying icons (instead of the [default icon component](../components/IconComponent.mdx))
|
|
1660
|
+
*
|
|
1661
|
+
* For code examples to the different customizations see our [customizations example application](https://github.com/GetStream/stream-chat-angular/tree/master/projects/customizations-example), specifically the [AppComponent](https://github.com/GetStream/stream-chat-angular/tree/master/projects/customizations-example/src/app) (see [README](https://github.com/GetStream/stream-chat-angular/blob/master/README.md#customization-examples) for instructions on how to start the application).
|
|
1662
|
+
*/
|
|
1663
|
+
this.iconTemplate$ = new BehaviorSubject(undefined);
|
|
1664
|
+
/**
|
|
1665
|
+
* Template for displaying the loading indicator (instead of the [default loading indicator](../components/LoadingIndicatorComponent.mdx))
|
|
1666
|
+
*
|
|
1667
|
+
* For code examples to the different customizations see our [customizations example application](https://github.com/GetStream/stream-chat-angular/tree/master/projects/customizations-example), specifically the [AppComponent](https://github.com/GetStream/stream-chat-angular/tree/master/projects/customizations-example/src/app) (see [README](https://github.com/GetStream/stream-chat-angular/blob/master/README.md#customization-examples) for instructions on how to start the application).
|
|
1668
|
+
*/
|
|
1669
|
+
this.loadingIndicatorTemplate$ = new BehaviorSubject(undefined);
|
|
1670
|
+
/**
|
|
1671
|
+
* Template for displaying the message actions box (instead of the [default message actions box](../components/MessageActionsBoxComponent.mdx))
|
|
1672
|
+
*
|
|
1673
|
+
* For code examples to the different customizations see our [customizations example application](https://github.com/GetStream/stream-chat-angular/tree/master/projects/customizations-example), specifically the [AppComponent](https://github.com/GetStream/stream-chat-angular/tree/master/projects/customizations-example/src/app) (see [README](https://github.com/GetStream/stream-chat-angular/blob/master/README.md#customization-examples) for instructions on how to start the application).
|
|
1674
|
+
*/
|
|
1675
|
+
this.messageActionsBoxTemplate$ = new BehaviorSubject(undefined);
|
|
1676
|
+
/**
|
|
1677
|
+
* The template used for displaying an item in the [message actions box](../components/MessageActionsBoxComponent.mdx)
|
|
1678
|
+
*
|
|
1679
|
+
* For code examples to the different customizations see our [customizations example application](https://github.com/GetStream/stream-chat-angular/tree/master/projects/customizations-example), specifically the [AppComponent](https://github.com/GetStream/stream-chat-angular/tree/master/projects/customizations-example/src/app) (see [README](https://github.com/GetStream/stream-chat-angular/blob/master/README.md#customization-examples) for instructions on how to start the application).
|
|
1680
|
+
*/
|
|
1681
|
+
this.messageActionsBoxItemTemplate$ = new BehaviorSubject(undefined);
|
|
1682
|
+
/**
|
|
1683
|
+
* The template used to display the reactions of a [message](../components/MessageComponent.mdx), and the selector to add a reaction to a message (instead of the [default message reactions component](../components/MessageReactionsComponent.mdx))
|
|
1684
|
+
*
|
|
1685
|
+
* For code examples to the different customizations see our [customizations example application](https://github.com/GetStream/stream-chat-angular/tree/master/projects/customizations-example), specifically the [AppComponent](https://github.com/GetStream/stream-chat-angular/tree/master/projects/customizations-example/src/app) (see [README](https://github.com/GetStream/stream-chat-angular/blob/master/README.md#customization-examples) for instructions on how to start the application).
|
|
1686
|
+
*/
|
|
1687
|
+
this.messageReactionsTemplate$ = new BehaviorSubject(undefined);
|
|
1688
|
+
/**
|
|
1689
|
+
* The template used to display a modal window (instead of the [default modal](../components/ModalComponent.mdx))
|
|
1690
|
+
*
|
|
1691
|
+
* For code examples to the different customizations see our [customizations example application](https://github.com/GetStream/stream-chat-angular/tree/master/projects/customizations-example), specifically the [AppComponent](https://github.com/GetStream/stream-chat-angular/tree/master/projects/customizations-example/src/app) (see [README](https://github.com/GetStream/stream-chat-angular/blob/master/README.md#customization-examples) for instructions on how to start the application).
|
|
1692
|
+
*/
|
|
1693
|
+
this.modalTemplate$ = new BehaviorSubject(undefined);
|
|
1694
|
+
/**
|
|
1695
|
+
* The template used to override the [default notification component](../components/NotificationComponent.mdx)
|
|
1696
|
+
*
|
|
1697
|
+
* For code examples to the different customizations see our [customizations example application](https://github.com/GetStream/stream-chat-angular/tree/master/projects/customizations-example), specifically the [AppComponent](https://github.com/GetStream/stream-chat-angular/tree/master/projects/customizations-example/src/app) (see [README](https://github.com/GetStream/stream-chat-angular/blob/master/README.md#customization-examples) for instructions on how to start the application).
|
|
1698
|
+
*/
|
|
1699
|
+
this.notificationTemplate$ = new BehaviorSubject(undefined);
|
|
1700
|
+
/**
|
|
1701
|
+
* The template used for header of a [thread](../components/ThreadComponent.mdx)
|
|
1702
|
+
*
|
|
1703
|
+
* For code examples to the different customizations see our [customizations example application](https://github.com/GetStream/stream-chat-angular/tree/master/projects/customizations-example), specifically the [AppComponent](https://github.com/GetStream/stream-chat-angular/tree/master/projects/customizations-example/src/app) (see [README](https://github.com/GetStream/stream-chat-angular/blob/master/README.md#customization-examples) for instructions on how to start the application).
|
|
1704
|
+
*/
|
|
1705
|
+
this.threadHeaderTemplate$ = new BehaviorSubject(undefined);
|
|
1706
|
+
}
|
|
1707
|
+
}
|
|
1708
|
+
CustomTemplatesService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: CustomTemplatesService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
1709
|
+
CustomTemplatesService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: CustomTemplatesService, providedIn: 'root' });
|
|
1710
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: CustomTemplatesService, decorators: [{
|
|
1711
|
+
type: Injectable,
|
|
1712
|
+
args: [{
|
|
1713
|
+
providedIn: 'root',
|
|
1714
|
+
}]
|
|
1715
|
+
}], ctorParameters: function () { return []; } });
|
|
1716
|
+
|
|
1717
|
+
/**
|
|
1718
|
+
* The `AvatarPlaceholder` component displays the [default avatar](./AvatarComponent.mdx) unless a [custom template](../services/CustomTemplatesService.mdx) is provided. This componet is used by the SDK internally, you likely won't need to use it.
|
|
1719
|
+
*/
|
|
1720
|
+
class AvatarPlaceholderComponent {
|
|
1721
|
+
constructor(customTemplatesService) {
|
|
1722
|
+
this.customTemplatesService = customTemplatesService;
|
|
1723
|
+
/**
|
|
1724
|
+
* The size in pixels of the avatar image.
|
|
1725
|
+
*/
|
|
1726
|
+
this.size = 32;
|
|
1727
|
+
}
|
|
1728
|
+
getAvatarContext() {
|
|
1729
|
+
return {
|
|
1730
|
+
name: this.name,
|
|
1731
|
+
imageUrl: this.imageUrl,
|
|
1732
|
+
size: this.size,
|
|
1733
|
+
};
|
|
1734
|
+
}
|
|
1735
|
+
}
|
|
1736
|
+
AvatarPlaceholderComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: AvatarPlaceholderComponent, deps: [{ token: CustomTemplatesService }], target: i0.ɵɵFactoryTarget.Component });
|
|
1737
|
+
AvatarPlaceholderComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.5", type: AvatarPlaceholderComponent, selector: "stream-avatar-placeholder", inputs: { name: "name", imageUrl: "imageUrl", size: "size" }, ngImport: i0, template: "<ng-template\n #defaultAvatar\n let-name=\"name\"\n let-imageUrl=\"imageUrl\"\n let-size=\"size\"\n>\n <stream-avatar\n [name]=\"name\"\n [imageUrl]=\"imageUrl\"\n [size]=\"size\"\n ></stream-avatar>\n</ng-template>\n<ng-container\n *ngTemplateOutlet=\"\n (customTemplatesService.avatarTemplate$ | async) || defaultAvatar;\n context: getAvatarContext()\n \"\n></ng-container>\n", components: [{ type: AvatarComponent, selector: "stream-avatar", inputs: ["name", "imageUrl", "size"] }], directives: [{ type: i3.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet"] }], pipes: { "async": i3.AsyncPipe } });
|
|
1738
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: AvatarPlaceholderComponent, decorators: [{
|
|
1739
|
+
type: Component,
|
|
1740
|
+
args: [{
|
|
1741
|
+
selector: 'stream-avatar-placeholder',
|
|
1742
|
+
templateUrl: './avatar-placeholder.component.html',
|
|
1743
|
+
styles: [],
|
|
1744
|
+
}]
|
|
1745
|
+
}], ctorParameters: function () { return [{ type: CustomTemplatesService }]; }, propDecorators: { name: [{
|
|
1746
|
+
type: Input
|
|
1747
|
+
}], imageUrl: [{
|
|
1748
|
+
type: Input
|
|
1749
|
+
}], size: [{
|
|
1750
|
+
type: Input
|
|
1751
|
+
}] } });
|
|
1752
|
+
|
|
1594
1753
|
/**
|
|
1595
1754
|
* The `Icon` component can be used to display different icons (i. e. message delivered icon).
|
|
1596
1755
|
*/
|
|
@@ -1598,7 +1757,7 @@ class IconComponent {
|
|
|
1598
1757
|
constructor() { }
|
|
1599
1758
|
}
|
|
1600
1759
|
IconComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: IconComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1601
|
-
IconComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.5", type: IconComponent, selector: "stream-icon", inputs: { icon: "icon", size: "size" }, ngImport: i0, template: "<svg\n data-testid=\"action-icon\"\n *ngIf=\"icon === 'action-icon'\"\n height=\"4\"\n viewBox=\"0 0 11 4\"\n width=\"11\"\n xmlns=\"http://www.w3.org/2000/svg\"\n>\n <path\n d=\"M1.5 3a1.5 1.5 0 1 1 0-3 1.5 1.5 0 0 1 0 3zm4 0a1.5 1.5 0 1 1 0-3 1.5 1.5 0 0 1 0 3zm4 0a1.5 1.5 0 1 1 0-3 1.5 1.5 0 0 1 0 3z\"\n fillRule=\"nonzero\"\n />\n</svg>\n<svg\n *ngIf=\"icon === 'delivered-icon'\"\n height=\"16\"\n width=\"16\"\n xmlns=\"http://www.w3.org/2000/svg\"\n data-testid=\"delivered-icon\"\n>\n <path\n d=\"M8 0a8 8 0 1 1 0 16A8 8 0 0 1 8 0zm3.72 6.633a.955.955 0 1 0-1.352-1.352L6.986 8.663 5.633 7.31A.956.956 0 1 0 4.28 8.663l2.029 2.028a.956.956 0 0 0 1.353 0l4.058-4.058z\"\n fill=\"#006CFF\"\n fillRule=\"evenodd\"\n />\n</svg>\n<svg\n *ngIf=\"icon === 'reaction-icon'\"\n height=\"12\"\n viewBox=\"0 0 12 12\"\n width=\"12\"\n xmlns=\"http://www.w3.org/2000/svg\"\n data-testid=\"reaction-icon\"\n>\n <g clipRule=\"evenodd\" fillRule=\"evenodd\">\n <path\n d=\"M6 1.2C3.3 1.2 1.2 3.3 1.2 6c0 2.7 2.1 4.8 4.8 4.8 2.7 0 4.8-2.1 4.8-4.8 0-2.7-2.1-4.8-4.8-4.8zM0 6c0-3.3 2.7-6 6-6s6 2.7 6 6-2.7 6-6 6-6-2.7-6-6z\"\n ></path>\n <path\n d=\"M5.4 4.5c0 .5-.4.9-.9.9s-.9-.4-.9-.9.4-.9.9-.9.9.4.9.9zM8.4 4.5c0 .5-.4.9-.9.9s-.9-.4-.9-.9.4-.9.9-.9.9.4.9.9zM3.3 6.7c.3-.2.6-.1.8.1.3.4.8.9 1.5 1 .6.2 1.4.1 2.4-1 .2-.2.6-.3.8 0 .2.2.3.6 0 .8-1.1 1.3-2.4 1.7-3.5 1.5-1-.2-1.8-.9-2.2-1.5-.2-.3-.1-.7.2-.9z\"\n ></path>\n </g>\n</svg>\n<svg\n data-testid=\"connection-error\"\n *ngIf=\"icon === 'connection-error'\"\n width=\"78px\"\n height=\"78px\"\n viewBox=\"0 0 78 78\"\n version=\"1.1\"\n xmlns=\"http://www.w3.org/2000/svg\"\n xmlns:xlink=\"http://www.w3.org/1999/xlink\"\n>\n <!-- Generator: Sketch 52.6 (67491) - http://www.bohemiancoding.com/sketch -->\n <title>Combined Shape</title>\n <desc>Created with Sketch.</desc>\n <g\n id=\"Interactions\"\n stroke=\"none\"\n stroke-width=\"1\"\n fill=\"none\"\n fill-rule=\"evenodd\"\n >\n <g\n id=\"Connection-Error-_-Connectivity\"\n transform=\"translate(-270.000000, -30.000000)\"\n fill=\"#CF1F25\"\n >\n <g\n id=\"109-network-connection\"\n transform=\"translate(270.000000, 30.000000)\"\n >\n <path\n d=\"M66.4609744,11.414231 C81.6225232,26.5757798 81.6225232,51.157545 66.4609744,66.3188467 C51.2994256,81.4803954 26.7176604,81.4803954 11.5563587,66.3188467 C-3.60519004,51.1572979 -3.60519004,26.5755327 11.5563587,11.414231 C26.7179075,-3.74731776 51.2996727,-3.74731776 66.4609744,11.414231 Z M54.7853215,45.8823776 L54.7853215,40.5882574 C54.7853215,39.613638 53.9952341,38.8235506 53.0206147,38.8235506 L44.9576695,38.8235506 L41.428256,42.3529641 L51.255555,42.3529641 L51.255555,45.8823776 L54.7853215,45.8823776 Z M40.6659027,43.1153174 L37.8988425,45.8823776 L40.6659027,45.8823776 L40.6659027,43.1153174 Z M51.1764962,56.4702653 L58.2353232,56.4702653 C59.2099355,56.4702653 60.00003,55.6801708 60.00003,54.7055585 L60.00003,51.176145 C60.00003,50.2015327 59.2099355,49.4114382 58.2353232,49.4114382 L51.1764962,49.4114382 C50.2018839,49.4114382 49.4117894,50.2015327 49.4117894,51.176145 L49.4117894,54.7055585 C49.4117894,55.6801708 50.2018839,56.4702653 51.1764962,56.4702653 Z M35.2941353,56.4702653 L42.3529624,56.4702653 C43.3275746,56.4702653 44.1176691,55.6801708 44.1176691,54.7055585 L44.1176691,51.176145 C44.1176691,50.2015327 43.3275746,49.4114382 42.3529624,49.4114382 L35.2941353,49.4114382 C34.319523,49.4114382 33.5294285,50.2015327 33.5294285,51.176145 L33.5294285,54.7055585 C33.5294285,55.6801708 34.319523,56.4702653 35.2941353,56.4702653 Z M56.6964989,19.0874231 C56.007381,18.3985134 54.8903216,18.3985134 54.2012036,19.087423 L45.882376,27.4062507 L45.882376,19.4117761 C45.882376,18.4371568 45.0922885,17.6470693 44.1176692,17.6470693 L33.5294286,17.6470693 C32.5548092,17.6470694 31.7647218,18.4371568 31.7647218,19.4117761 L31.7647218,30.0000167 C31.7647219,30.9746363 32.5548092,31.7647237 33.5294285,31.7647237 L41.5239031,31.7647237 L34.4650761,38.8235508 L24.7058947,38.8235508 C23.7312753,38.8235508 22.9411879,39.6136382 22.9411879,40.5882575 L22.9411879,45.8823778 L26.4706014,45.8823778 L26.4706014,42.3529643 L30.9356624,42.3529643 L23.8768354,49.4117914 L19.4117743,49.4117914 C18.4371549,49.4117914 17.6470675,50.2018788 17.6470675,51.1764981 L17.6470675,54.7059117 C17.6504049,54.9674302 17.7129076,55.2248042 17.8298886,55.4587302 L16.4456526,56.8429662 C15.7446193,57.5200453 15.7252005,58.6372282 16.4022825,59.3382615 C17.0793616,60.0392948 18.1965445,60.0587136 18.8975778,59.3816316 C18.9122847,59.3674273 18.9267436,59.3529684 18.940948,59.3382615 L56.6964963,21.5830662 C57.3856425,20.8939094 57.3856425,19.7765747 56.6964963,19.0874179 Z\"\n id=\"Combined-Shape\"\n ></path>\n </g>\n </g>\n </g>\n</svg>\n<svg\n *ngIf=\"icon === 'send'\"\n data-testid=\"send\"\n height=\"17\"\n viewBox=\"0 0 18 17\"\n width=\"18\"\n xmlns=\"http://www.w3.org/2000/svg\"\n>\n <title translate>streamChat.Send</title>\n <path\n d=\"M0 17.015l17.333-8.508L0 0v6.617l12.417 1.89L0 10.397z\"\n fill=\"#006cff\"\n fillRule=\"evenodd\"\n />\n</svg>\n<svg\n *ngIf=\"icon === 'file-upload'\"\n data-testid=\"file-upload\"\n height=\"14\"\n width=\"14\"\n xmlns=\"http://www.w3.org/2000/svg\"\n>\n <title translate>streamChat.Attach files</title>\n <path\n d=\"M1.667.333h10.666c.737 0 1.334.597 1.334 1.334v10.666c0 .737-.597 1.334-1.334 1.334H1.667a1.333 1.333 0 0 1-1.334-1.334V1.667C.333.93.93.333 1.667.333zm2 1.334a1.667 1.667 0 1 0 0 3.333 1.667 1.667 0 0 0 0-3.333zm-2 9.333v1.333h10.666v-4l-2-2-4 4-2-2L1.667 11z\"\n fillRule=\"nonzero\"\n />\n</svg>\n<svg\n data-testid=\"retry\"\n *ngIf=\"icon === 'retry'\"\n width=\"22\"\n height=\"20\"\n viewBox=\"0 0 22 20\"\n xmlns=\"http://www.w3.org/2000/svg\"\n>\n <path\n d=\"M20 5.535V2a1 1 0 0 1 2 0v6a1 1 0 0 1-1 1h-6a1 1 0 0 1 0-2h3.638l-2.975-2.653a8 8 0 1 0 1.884 8.32 1 1 0 1 1 1.886.666A10 10 0 1 1 5.175 1.245c3.901-2.15 8.754-1.462 11.88 1.667L20 5.535z\"\n fill=\"#FFF\"\n fill-rule=\"nonzero\"\n />\n</svg>\n<svg\n *ngIf=\"icon === 'close'\"\n data-testid=\"close\"\n width=\"28\"\n height=\"28\"\n viewBox=\"0 0 28 28\"\n xmlns=\"http://www.w3.org/2000/svg\"\n xmlns:xlink=\"http://www.w3.org/1999/xlink\"\n>\n <defs>\n <path\n d=\"M465 5c5.53 0 10 4.47 10 10s-4.47 10-10 10-10-4.47-10-10 4.47-10 10-10zm3.59 5L465 13.59 461.41 10 460 11.41l3.59 3.59-3.59 3.59 1.41 1.41 3.59-3.59 3.59 3.59 1.41-1.41-3.59-3.59 3.59-3.59-1.41-1.41z\"\n id=\"b\"\n />\n <filter\n x=\"-30%\"\n y=\"-30%\"\n width=\"160%\"\n height=\"160%\"\n filterUnits=\"objectBoundingBox\"\n id=\"a\"\n >\n <feOffset in=\"SourceAlpha\" result=\"shadowOffsetOuter1\" />\n <feGaussianBlur\n stdDeviation=\"2\"\n in=\"shadowOffsetOuter1\"\n result=\"shadowBlurOuter1\"\n />\n <feColorMatrix\n values=\"0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.5 0\"\n in=\"shadowBlurOuter1\"\n />\n </filter>\n </defs>\n <g transform=\"translate(-451 -1)\" fill-rule=\"nonzero\" fill=\"none\">\n <use fill=\"#000\" filter=\"url(#a)\" xlink:href=\"#b\" />\n <use fill=\"#FFF\" fill-rule=\"evenodd\" xlink:href=\"#b\" />\n </g>\n</svg>\n<svg\n *ngIf=\"icon === 'file'\"\n data-testid=\"file\"\n className=\"rfu-file-icon--small fa-file-fallback\"\n [attr.height]=\"size || 20\"\n [attr.width]=\"size || 20\"\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 384 512\"\n>\n <path\n d=\"M369.9 97.9L286 14C277 5 264.8-.1 252.1-.1H48C21.5 0 0 21.5 0 48v416c0 26.5 21.5 48 48 48h288c26.5 0 48-21.5 48-48V131.9c0-12.7-5.1-25-14.1-34zM332.1 128H256V51.9l76.1 76.1zM48 464V48h160v104c0 13.3 10.7 24 24 24h104v288H48z\"\n fill=\"#414D54\"\n />\n</svg>\n<svg\n *ngIf=\"icon === 'reply'\"\n data-testid=\"reply\"\n height=\"15\"\n width=\"18\"\n xmlns=\"http://www.w3.org/2000/svg\"\n>\n <path\n d=\"M.56 10.946H.06l-.002-.498L.025.92a.5.5 0 1 1 1-.004l.032 9.029H9.06v-4l9 4.5-9 4.5v-4H.56z\"\n fillRule=\"nonzero\"\n />\n</svg>\n<svg\n height=\"10\"\n width=\"10\"\n xmlns=\"http://www.w3.org/2000/svg\"\n data-testid=\"close-no-outline\"\n *ngIf=\"icon === 'close-no-outline'\"\n>\n <path\n d=\"M9.916 1.027L8.973.084 5 4.058 1.027.084l-.943.943L4.058 5 .084 8.973l.943.943L5 5.942l3.973 3.974.943-.943L5.942 5z\"\n fillRule=\"evenodd\"\n />\n</svg>\n<svg\n height=\"10\"\n width=\"14\"\n xmlns=\"http://www.w3.org/2000/svg\"\n data-testid=\"reply-in-thread\"\n *ngIf=\"icon === 'reply-in-thread'\"\n>\n <path\n d=\"M8.516 3c4.78 0 4.972 6.5 4.972 6.5-1.6-2.906-2.847-3.184-4.972-3.184v2.872L3.772 4.994 8.516.5V3zM.484 5l4.5-4.237v1.78L2.416 5l2.568 2.125v1.828L.484 5z\"\n fillRule=\"evenodd\"\n />\n</svg>\n<svg\n *ngIf=\"icon === 'arrow-left'\"\n data-testid=\"arrow-left\"\n width=\"24\"\n height=\"24\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n>\n <path\n d=\"M15.7049 7.41L14.2949 6L8.29492 12L14.2949 18L15.7049 16.59L11.1249 12L15.7049 7.41Z\"\n fill=\"var(--black)\"\n />\n</svg>\n\n<svg\n *ngIf=\"icon === 'arrow-right'\"\n data-testid=\"arrow-right\"\n width=\"24\"\n height=\"24\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n>\n <path\n d=\"M9.70492 6L8.29492 7.41L12.8749 12L8.29492 16.59L9.70492 18L15.7049 12L9.70492 6Z\"\n fill=\"var(--black)\"\n />\n</svg>\n<svg\n *ngIf=\"icon === 'menu'\"\n data-testid=\"menu\"\n width=\"24\"\n height=\"24\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n>\n <path\n fill-rule=\"evenodd\"\n clip-rule=\"evenodd\"\n d=\"M3 8V6H21V8H3ZM3 13H21V11H3V13ZM3 18H21V16H3V18Z\"\n fill=\"black\"\n />\n</svg>\n", directives: [{ type: i6.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i2.TranslateDirective, selector: "[translate],[ngx-translate]", inputs: ["translate", "translateParams"] }] });
|
|
1760
|
+
IconComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.5", type: IconComponent, selector: "stream-icon", inputs: { icon: "icon", size: "size" }, ngImport: i0, template: "<svg\n data-testid=\"action-icon\"\n *ngIf=\"icon === 'action-icon'\"\n height=\"4\"\n viewBox=\"0 0 11 4\"\n width=\"11\"\n xmlns=\"http://www.w3.org/2000/svg\"\n>\n <path\n d=\"M1.5 3a1.5 1.5 0 1 1 0-3 1.5 1.5 0 0 1 0 3zm4 0a1.5 1.5 0 1 1 0-3 1.5 1.5 0 0 1 0 3zm4 0a1.5 1.5 0 1 1 0-3 1.5 1.5 0 0 1 0 3z\"\n fillRule=\"nonzero\"\n />\n</svg>\n<svg\n *ngIf=\"icon === 'delivered-icon'\"\n height=\"16\"\n width=\"16\"\n xmlns=\"http://www.w3.org/2000/svg\"\n data-testid=\"delivered-icon\"\n>\n <path\n d=\"M8 0a8 8 0 1 1 0 16A8 8 0 0 1 8 0zm3.72 6.633a.955.955 0 1 0-1.352-1.352L6.986 8.663 5.633 7.31A.956.956 0 1 0 4.28 8.663l2.029 2.028a.956.956 0 0 0 1.353 0l4.058-4.058z\"\n fill=\"#006CFF\"\n fillRule=\"evenodd\"\n />\n</svg>\n<svg\n *ngIf=\"icon === 'reaction-icon'\"\n height=\"12\"\n viewBox=\"0 0 12 12\"\n width=\"12\"\n xmlns=\"http://www.w3.org/2000/svg\"\n data-testid=\"reaction-icon\"\n>\n <g clipRule=\"evenodd\" fillRule=\"evenodd\">\n <path\n d=\"M6 1.2C3.3 1.2 1.2 3.3 1.2 6c0 2.7 2.1 4.8 4.8 4.8 2.7 0 4.8-2.1 4.8-4.8 0-2.7-2.1-4.8-4.8-4.8zM0 6c0-3.3 2.7-6 6-6s6 2.7 6 6-2.7 6-6 6-6-2.7-6-6z\"\n ></path>\n <path\n d=\"M5.4 4.5c0 .5-.4.9-.9.9s-.9-.4-.9-.9.4-.9.9-.9.9.4.9.9zM8.4 4.5c0 .5-.4.9-.9.9s-.9-.4-.9-.9.4-.9.9-.9.9.4.9.9zM3.3 6.7c.3-.2.6-.1.8.1.3.4.8.9 1.5 1 .6.2 1.4.1 2.4-1 .2-.2.6-.3.8 0 .2.2.3.6 0 .8-1.1 1.3-2.4 1.7-3.5 1.5-1-.2-1.8-.9-2.2-1.5-.2-.3-.1-.7.2-.9z\"\n ></path>\n </g>\n</svg>\n<svg\n data-testid=\"connection-error\"\n *ngIf=\"icon === 'connection-error'\"\n width=\"78px\"\n height=\"78px\"\n viewBox=\"0 0 78 78\"\n version=\"1.1\"\n xmlns=\"http://www.w3.org/2000/svg\"\n xmlns:xlink=\"http://www.w3.org/1999/xlink\"\n>\n <!-- Generator: Sketch 52.6 (67491) - http://www.bohemiancoding.com/sketch -->\n <title>Combined Shape</title>\n <desc>Created with Sketch.</desc>\n <g\n id=\"Interactions\"\n stroke=\"none\"\n stroke-width=\"1\"\n fill=\"none\"\n fill-rule=\"evenodd\"\n >\n <g\n id=\"Connection-Error-_-Connectivity\"\n transform=\"translate(-270.000000, -30.000000)\"\n fill=\"#CF1F25\"\n >\n <g\n id=\"109-network-connection\"\n transform=\"translate(270.000000, 30.000000)\"\n >\n <path\n d=\"M66.4609744,11.414231 C81.6225232,26.5757798 81.6225232,51.157545 66.4609744,66.3188467 C51.2994256,81.4803954 26.7176604,81.4803954 11.5563587,66.3188467 C-3.60519004,51.1572979 -3.60519004,26.5755327 11.5563587,11.414231 C26.7179075,-3.74731776 51.2996727,-3.74731776 66.4609744,11.414231 Z M54.7853215,45.8823776 L54.7853215,40.5882574 C54.7853215,39.613638 53.9952341,38.8235506 53.0206147,38.8235506 L44.9576695,38.8235506 L41.428256,42.3529641 L51.255555,42.3529641 L51.255555,45.8823776 L54.7853215,45.8823776 Z M40.6659027,43.1153174 L37.8988425,45.8823776 L40.6659027,45.8823776 L40.6659027,43.1153174 Z M51.1764962,56.4702653 L58.2353232,56.4702653 C59.2099355,56.4702653 60.00003,55.6801708 60.00003,54.7055585 L60.00003,51.176145 C60.00003,50.2015327 59.2099355,49.4114382 58.2353232,49.4114382 L51.1764962,49.4114382 C50.2018839,49.4114382 49.4117894,50.2015327 49.4117894,51.176145 L49.4117894,54.7055585 C49.4117894,55.6801708 50.2018839,56.4702653 51.1764962,56.4702653 Z M35.2941353,56.4702653 L42.3529624,56.4702653 C43.3275746,56.4702653 44.1176691,55.6801708 44.1176691,54.7055585 L44.1176691,51.176145 C44.1176691,50.2015327 43.3275746,49.4114382 42.3529624,49.4114382 L35.2941353,49.4114382 C34.319523,49.4114382 33.5294285,50.2015327 33.5294285,51.176145 L33.5294285,54.7055585 C33.5294285,55.6801708 34.319523,56.4702653 35.2941353,56.4702653 Z M56.6964989,19.0874231 C56.007381,18.3985134 54.8903216,18.3985134 54.2012036,19.087423 L45.882376,27.4062507 L45.882376,19.4117761 C45.882376,18.4371568 45.0922885,17.6470693 44.1176692,17.6470693 L33.5294286,17.6470693 C32.5548092,17.6470694 31.7647218,18.4371568 31.7647218,19.4117761 L31.7647218,30.0000167 C31.7647219,30.9746363 32.5548092,31.7647237 33.5294285,31.7647237 L41.5239031,31.7647237 L34.4650761,38.8235508 L24.7058947,38.8235508 C23.7312753,38.8235508 22.9411879,39.6136382 22.9411879,40.5882575 L22.9411879,45.8823778 L26.4706014,45.8823778 L26.4706014,42.3529643 L30.9356624,42.3529643 L23.8768354,49.4117914 L19.4117743,49.4117914 C18.4371549,49.4117914 17.6470675,50.2018788 17.6470675,51.1764981 L17.6470675,54.7059117 C17.6504049,54.9674302 17.7129076,55.2248042 17.8298886,55.4587302 L16.4456526,56.8429662 C15.7446193,57.5200453 15.7252005,58.6372282 16.4022825,59.3382615 C17.0793616,60.0392948 18.1965445,60.0587136 18.8975778,59.3816316 C18.9122847,59.3674273 18.9267436,59.3529684 18.940948,59.3382615 L56.6964963,21.5830662 C57.3856425,20.8939094 57.3856425,19.7765747 56.6964963,19.0874179 Z\"\n id=\"Combined-Shape\"\n ></path>\n </g>\n </g>\n </g>\n</svg>\n<svg\n *ngIf=\"icon === 'send'\"\n data-testid=\"send\"\n height=\"17\"\n viewBox=\"0 0 18 17\"\n width=\"18\"\n xmlns=\"http://www.w3.org/2000/svg\"\n>\n <title translate>streamChat.Send</title>\n <path\n d=\"M0 17.015l17.333-8.508L0 0v6.617l12.417 1.89L0 10.397z\"\n fill=\"#006cff\"\n fillRule=\"evenodd\"\n />\n</svg>\n<svg\n *ngIf=\"icon === 'file-upload'\"\n data-testid=\"file-upload\"\n height=\"14\"\n width=\"14\"\n xmlns=\"http://www.w3.org/2000/svg\"\n>\n <title translate>streamChat.Attach files</title>\n <path\n d=\"M1.667.333h10.666c.737 0 1.334.597 1.334 1.334v10.666c0 .737-.597 1.334-1.334 1.334H1.667a1.333 1.333 0 0 1-1.334-1.334V1.667C.333.93.93.333 1.667.333zm2 1.334a1.667 1.667 0 1 0 0 3.333 1.667 1.667 0 0 0 0-3.333zm-2 9.333v1.333h10.666v-4l-2-2-4 4-2-2L1.667 11z\"\n fillRule=\"nonzero\"\n />\n</svg>\n<svg\n data-testid=\"retry\"\n *ngIf=\"icon === 'retry'\"\n width=\"22\"\n height=\"20\"\n viewBox=\"0 0 22 20\"\n xmlns=\"http://www.w3.org/2000/svg\"\n>\n <path\n d=\"M20 5.535V2a1 1 0 0 1 2 0v6a1 1 0 0 1-1 1h-6a1 1 0 0 1 0-2h3.638l-2.975-2.653a8 8 0 1 0 1.884 8.32 1 1 0 1 1 1.886.666A10 10 0 1 1 5.175 1.245c3.901-2.15 8.754-1.462 11.88 1.667L20 5.535z\"\n fill=\"#FFF\"\n fill-rule=\"nonzero\"\n />\n</svg>\n<svg\n *ngIf=\"icon === 'close'\"\n data-testid=\"close\"\n width=\"28\"\n height=\"28\"\n viewBox=\"0 0 28 28\"\n xmlns=\"http://www.w3.org/2000/svg\"\n xmlns:xlink=\"http://www.w3.org/1999/xlink\"\n>\n <defs>\n <path\n d=\"M465 5c5.53 0 10 4.47 10 10s-4.47 10-10 10-10-4.47-10-10 4.47-10 10-10zm3.59 5L465 13.59 461.41 10 460 11.41l3.59 3.59-3.59 3.59 1.41 1.41 3.59-3.59 3.59 3.59 1.41-1.41-3.59-3.59 3.59-3.59-1.41-1.41z\"\n id=\"b\"\n />\n <filter\n x=\"-30%\"\n y=\"-30%\"\n width=\"160%\"\n height=\"160%\"\n filterUnits=\"objectBoundingBox\"\n id=\"a\"\n >\n <feOffset in=\"SourceAlpha\" result=\"shadowOffsetOuter1\" />\n <feGaussianBlur\n stdDeviation=\"2\"\n in=\"shadowOffsetOuter1\"\n result=\"shadowBlurOuter1\"\n />\n <feColorMatrix\n values=\"0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.5 0\"\n in=\"shadowBlurOuter1\"\n />\n </filter>\n </defs>\n <g transform=\"translate(-451 -1)\" fill-rule=\"nonzero\" fill=\"none\">\n <use fill=\"#000\" filter=\"url(#a)\" xlink:href=\"#b\" />\n <use fill=\"#FFF\" fill-rule=\"evenodd\" xlink:href=\"#b\" />\n </g>\n</svg>\n<svg\n *ngIf=\"icon === 'file'\"\n data-testid=\"file\"\n className=\"rfu-file-icon--small fa-file-fallback\"\n [attr.height]=\"size || 20\"\n [attr.width]=\"size || 20\"\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 384 512\"\n>\n <path\n d=\"M369.9 97.9L286 14C277 5 264.8-.1 252.1-.1H48C21.5 0 0 21.5 0 48v416c0 26.5 21.5 48 48 48h288c26.5 0 48-21.5 48-48V131.9c0-12.7-5.1-25-14.1-34zM332.1 128H256V51.9l76.1 76.1zM48 464V48h160v104c0 13.3 10.7 24 24 24h104v288H48z\"\n fill=\"#414D54\"\n />\n</svg>\n<svg\n *ngIf=\"icon === 'reply'\"\n data-testid=\"reply\"\n height=\"15\"\n width=\"18\"\n xmlns=\"http://www.w3.org/2000/svg\"\n>\n <path\n d=\"M.56 10.946H.06l-.002-.498L.025.92a.5.5 0 1 1 1-.004l.032 9.029H9.06v-4l9 4.5-9 4.5v-4H.56z\"\n fillRule=\"nonzero\"\n />\n</svg>\n<svg\n height=\"10\"\n width=\"10\"\n xmlns=\"http://www.w3.org/2000/svg\"\n data-testid=\"close-no-outline\"\n *ngIf=\"icon === 'close-no-outline'\"\n>\n <path\n d=\"M9.916 1.027L8.973.084 5 4.058 1.027.084l-.943.943L4.058 5 .084 8.973l.943.943L5 5.942l3.973 3.974.943-.943L5.942 5z\"\n fillRule=\"evenodd\"\n />\n</svg>\n<svg\n height=\"10\"\n width=\"14\"\n xmlns=\"http://www.w3.org/2000/svg\"\n data-testid=\"reply-in-thread\"\n *ngIf=\"icon === 'reply-in-thread'\"\n>\n <path\n d=\"M8.516 3c4.78 0 4.972 6.5 4.972 6.5-1.6-2.906-2.847-3.184-4.972-3.184v2.872L3.772 4.994 8.516.5V3zM.484 5l4.5-4.237v1.78L2.416 5l2.568 2.125v1.828L.484 5z\"\n fillRule=\"evenodd\"\n />\n</svg>\n<svg\n *ngIf=\"icon === 'arrow-left'\"\n data-testid=\"arrow-left\"\n width=\"24\"\n height=\"24\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n>\n <path\n d=\"M15.7049 7.41L14.2949 6L8.29492 12L14.2949 18L15.7049 16.59L11.1249 12L15.7049 7.41Z\"\n fill=\"var(--black)\"\n />\n</svg>\n\n<svg\n *ngIf=\"icon === 'arrow-right'\"\n data-testid=\"arrow-right\"\n width=\"24\"\n height=\"24\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n>\n <path\n d=\"M9.70492 6L8.29492 7.41L12.8749 12L8.29492 16.59L9.70492 18L15.7049 12L9.70492 6Z\"\n fill=\"var(--black)\"\n />\n</svg>\n<svg\n *ngIf=\"icon === 'menu'\"\n data-testid=\"menu\"\n width=\"24\"\n height=\"24\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n>\n <path\n fill-rule=\"evenodd\"\n clip-rule=\"evenodd\"\n d=\"M3 8V6H21V8H3ZM3 13H21V11H3V13ZM3 18H21V16H3V18Z\"\n fill=\"black\"\n />\n</svg>\n", directives: [{ type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i2.TranslateDirective, selector: "[translate],[ngx-translate]", inputs: ["translate", "translateParams"] }] });
|
|
1602
1761
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: IconComponent, decorators: [{
|
|
1603
1762
|
type: Component,
|
|
1604
1763
|
args: [{
|
|
@@ -1612,6 +1771,35 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImpor
|
|
|
1612
1771
|
type: Input
|
|
1613
1772
|
}] } });
|
|
1614
1773
|
|
|
1774
|
+
/**
|
|
1775
|
+
* The `IconPlaceholder` component displays the [default icons](./IconComponent.mdx) unless a [custom template](../services/CustomTemplatesService.mdx) is provided. This componet is used by the SDK internally, you likely won't need to use it.
|
|
1776
|
+
*/
|
|
1777
|
+
class IconPlaceholderComponent {
|
|
1778
|
+
constructor(customTemplatesService) {
|
|
1779
|
+
this.customTemplatesService = customTemplatesService;
|
|
1780
|
+
}
|
|
1781
|
+
getIconContext() {
|
|
1782
|
+
return {
|
|
1783
|
+
icon: this.icon,
|
|
1784
|
+
size: this.size,
|
|
1785
|
+
};
|
|
1786
|
+
}
|
|
1787
|
+
}
|
|
1788
|
+
IconPlaceholderComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: IconPlaceholderComponent, deps: [{ token: CustomTemplatesService }], target: i0.ɵɵFactoryTarget.Component });
|
|
1789
|
+
IconPlaceholderComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.5", type: IconPlaceholderComponent, selector: "stream-icon-placeholder", inputs: { icon: "icon", size: "size" }, ngImport: i0, template: "<ng-template #defaultIcon let-icon=\"icon\" let-size=\"size\">\n <stream-icon [icon]=\"icon\" [size]=\"size\"></stream-icon>\n</ng-template>\n<ng-container\n *ngTemplateOutlet=\"\n (customTemplatesService.iconTemplate$ | async) || defaultIcon;\n context: getIconContext()\n \"\n></ng-container>\n", components: [{ type: IconComponent, selector: "stream-icon", inputs: ["icon", "size"] }], directives: [{ type: i3.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet"] }], pipes: { "async": i3.AsyncPipe } });
|
|
1790
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: IconPlaceholderComponent, decorators: [{
|
|
1791
|
+
type: Component,
|
|
1792
|
+
args: [{
|
|
1793
|
+
selector: 'stream-icon-placeholder',
|
|
1794
|
+
templateUrl: './icon-placeholder.component.html',
|
|
1795
|
+
styles: [],
|
|
1796
|
+
}]
|
|
1797
|
+
}], ctorParameters: function () { return [{ type: CustomTemplatesService }]; }, propDecorators: { icon: [{
|
|
1798
|
+
type: Input
|
|
1799
|
+
}], size: [{
|
|
1800
|
+
type: Input
|
|
1801
|
+
}] } });
|
|
1802
|
+
|
|
1615
1803
|
/**
|
|
1616
1804
|
* The `LoadingIndicator` component displays a spinner to indicate that an action is in progress.
|
|
1617
1805
|
*/
|
|
@@ -1628,7 +1816,7 @@ class LoadingIndicatorComponent {
|
|
|
1628
1816
|
}
|
|
1629
1817
|
}
|
|
1630
1818
|
LoadingIndicatorComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: LoadingIndicatorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1631
|
-
LoadingIndicatorComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.5", type: LoadingIndicatorComponent, selector: "stream-loading-indicator", inputs: { size: "size", color: "color" }, ngImport: i0, template: "<div class=\"str-chat__loading-indicator\">\n <svg\n [attr.height]=\"size\"\n viewBox=\"0 0 30 30\"\n [attr.width]=\"size\"\n data-testid=\"loading-indicator\"\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <defs>\n <linearGradient id=\"a\" x1=\"50%\" x2=\"50%\" y1=\"0%\" y2=\"100%\">\n <stop offset=\"0%\" stop-color=\"#FFF\" stop-opacity=\"0\" />\n <stop\n data-testid=\"stop-color\"\n offset=\"100%\"\n [attr.stop-color]=\"color\"\n stop-opacity=\"1\"\n [ngStyle]=\"{ stopColor: color }\"\n />\n </linearGradient>\n </defs>\n <path\n d=\"M2.518 23.321l1.664-1.11A12.988 12.988 0 0 0 15 28c7.18 0 13-5.82 13-13S22.18 2 15 2V0c8.284 0 15 6.716 15 15 0 8.284-6.716 15-15 15-5.206 0-9.792-2.652-12.482-6.679z\"\n fill=\"url(#a)\"\n fillRule=\"evenodd\"\n />\n </svg>\n</div>\n", directives: [{ type:
|
|
1819
|
+
LoadingIndicatorComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.5", type: LoadingIndicatorComponent, selector: "stream-loading-indicator", inputs: { size: "size", color: "color" }, ngImport: i0, template: "<div class=\"str-chat__loading-indicator\">\n <svg\n [attr.height]=\"size\"\n viewBox=\"0 0 30 30\"\n [attr.width]=\"size\"\n data-testid=\"loading-indicator\"\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <defs>\n <linearGradient id=\"a\" x1=\"50%\" x2=\"50%\" y1=\"0%\" y2=\"100%\">\n <stop offset=\"0%\" stop-color=\"#FFF\" stop-opacity=\"0\" />\n <stop\n data-testid=\"stop-color\"\n offset=\"100%\"\n [attr.stop-color]=\"color\"\n stop-opacity=\"1\"\n [ngStyle]=\"{ stopColor: color }\"\n />\n </linearGradient>\n </defs>\n <path\n d=\"M2.518 23.321l1.664-1.11A12.988 12.988 0 0 0 15 28c7.18 0 13-5.82 13-13S22.18 2 15 2V0c8.284 0 15 6.716 15 15 0 8.284-6.716 15-15 15-5.206 0-9.792-2.652-12.482-6.679z\"\n fill=\"url(#a)\"\n fillRule=\"evenodd\"\n />\n </svg>\n</div>\n", directives: [{ type: i3.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }] });
|
|
1632
1820
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: LoadingIndicatorComponent, decorators: [{
|
|
1633
1821
|
type: Component,
|
|
1634
1822
|
args: [{
|
|
@@ -1642,6 +1830,113 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImpor
|
|
|
1642
1830
|
type: Input
|
|
1643
1831
|
}] } });
|
|
1644
1832
|
|
|
1833
|
+
/**
|
|
1834
|
+
* The `LoadingInficatorPlaceholder` component displays the [default loading indicator](./LoadingIndicatorComponent.mdx) unless a [custom template](../services/CustomTemplatesService.mdx) is provided. This componet is used by the SDK internally, you likely won't need to use it.
|
|
1835
|
+
*/
|
|
1836
|
+
class LoadingIndicatorPlaceholderComponent {
|
|
1837
|
+
constructor(customTemplatesService) {
|
|
1838
|
+
this.customTemplatesService = customTemplatesService;
|
|
1839
|
+
/**
|
|
1840
|
+
* The size of the indicator (in pixels)
|
|
1841
|
+
*/
|
|
1842
|
+
this.size = 15;
|
|
1843
|
+
/**
|
|
1844
|
+
* The color of the indicator
|
|
1845
|
+
*/
|
|
1846
|
+
this.color = '#006CFF';
|
|
1847
|
+
}
|
|
1848
|
+
getLoadingIndicatorContext() {
|
|
1849
|
+
return {
|
|
1850
|
+
size: this.size,
|
|
1851
|
+
color: this.color,
|
|
1852
|
+
};
|
|
1853
|
+
}
|
|
1854
|
+
}
|
|
1855
|
+
LoadingIndicatorPlaceholderComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: LoadingIndicatorPlaceholderComponent, deps: [{ token: CustomTemplatesService }], target: i0.ɵɵFactoryTarget.Component });
|
|
1856
|
+
LoadingIndicatorPlaceholderComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.5", type: LoadingIndicatorPlaceholderComponent, selector: "stream-loading-indicator-placeholder", inputs: { size: "size", color: "color" }, ngImport: i0, template: "<ng-template #defaultLoadingIndicator let-size=\"size\" let-color=\"color\">\n <stream-loading-indicator\n [size]=\"size\"\n [color]=\"color\"\n ></stream-loading-indicator>\n</ng-template>\n<ng-container\n *ngTemplateOutlet=\"\n (customTemplatesService.loadingIndicatorTemplate$ | async) ||\n defaultLoadingIndicator;\n context: getLoadingIndicatorContext()\n \"\n></ng-container>\n", components: [{ type: LoadingIndicatorComponent, selector: "stream-loading-indicator", inputs: ["size", "color"] }], directives: [{ type: i3.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet"] }], pipes: { "async": i3.AsyncPipe } });
|
|
1857
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: LoadingIndicatorPlaceholderComponent, decorators: [{
|
|
1858
|
+
type: Component,
|
|
1859
|
+
args: [{
|
|
1860
|
+
selector: 'stream-loading-indicator-placeholder',
|
|
1861
|
+
templateUrl: './loading-indicator-placeholder.component.html',
|
|
1862
|
+
styles: [],
|
|
1863
|
+
}]
|
|
1864
|
+
}], ctorParameters: function () { return [{ type: CustomTemplatesService }]; }, propDecorators: { size: [{
|
|
1865
|
+
type: Input
|
|
1866
|
+
}], color: [{
|
|
1867
|
+
type: Input
|
|
1868
|
+
}] } });
|
|
1869
|
+
|
|
1870
|
+
/**
|
|
1871
|
+
* 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.
|
|
1872
|
+
*/
|
|
1873
|
+
class ModalComponent {
|
|
1874
|
+
constructor() {
|
|
1875
|
+
/**
|
|
1876
|
+
* If `true` the modal will be displayed, if `false` the modal will be hidden
|
|
1877
|
+
*/
|
|
1878
|
+
this.isOpen = false;
|
|
1879
|
+
/**
|
|
1880
|
+
* Emits `true` if the modal becomes visible, and `false` if the modal is closed.
|
|
1881
|
+
*/
|
|
1882
|
+
this.isOpenChange = new EventEmitter();
|
|
1883
|
+
this.watchForEscPress = (event) => {
|
|
1884
|
+
if (event.key === 'Escape') {
|
|
1885
|
+
this.close();
|
|
1886
|
+
}
|
|
1887
|
+
};
|
|
1888
|
+
this.stopWatchForEscPress = () => {
|
|
1889
|
+
window.removeEventListener('keyup', this.watchForEscPress);
|
|
1890
|
+
};
|
|
1891
|
+
this.watchForOutsideClicks = (event) => {
|
|
1892
|
+
var _a;
|
|
1893
|
+
if (!((_a = this.innerContainer) === null || _a === void 0 ? void 0 : _a.nativeElement.contains(event.target))) {
|
|
1894
|
+
this.close();
|
|
1895
|
+
}
|
|
1896
|
+
};
|
|
1897
|
+
}
|
|
1898
|
+
ngOnChanges(changes) {
|
|
1899
|
+
if (changes.isOpen) {
|
|
1900
|
+
if (this.isOpen) {
|
|
1901
|
+
window.addEventListener('keyup', this.watchForEscPress);
|
|
1902
|
+
setTimeout(() => window.addEventListener('click', this.watchForOutsideClicks), 0);
|
|
1903
|
+
}
|
|
1904
|
+
else {
|
|
1905
|
+
this.stopWatchForOutsideClicks();
|
|
1906
|
+
this.stopWatchForEscPress();
|
|
1907
|
+
}
|
|
1908
|
+
}
|
|
1909
|
+
}
|
|
1910
|
+
close() {
|
|
1911
|
+
this.isOpen = false;
|
|
1912
|
+
this.isOpenChange.emit(false);
|
|
1913
|
+
this.stopWatchForOutsideClicks();
|
|
1914
|
+
this.stopWatchForEscPress();
|
|
1915
|
+
}
|
|
1916
|
+
stopWatchForOutsideClicks() {
|
|
1917
|
+
window.removeEventListener('click', this.watchForOutsideClicks);
|
|
1918
|
+
}
|
|
1919
|
+
}
|
|
1920
|
+
ModalComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: ModalComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1921
|
+
ModalComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.5", type: ModalComponent, selector: "stream-modal", inputs: { isOpen: "isOpen", content: "content" }, outputs: { isOpenChange: "isOpenChange" }, viewQueries: [{ propertyName: "innerContainer", first: true, predicate: ["modalInner"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div\n data-testid=\"modal\"\n class=\"str-chat__modal str-chat__modal--{{ isOpen ? 'open' : 'close' }}\"\n>\n <div\n data-testid=\"close\"\n class=\"str-chat__modal__close-button\"\n (click)=\"close()\"\n (keyup.enter)=\"close()\"\n translate\n >\n streamChat.Close\n <stream-icon-placeholder icon=\"close\"></stream-icon-placeholder>\n </div>\n <div class=\"str-chat__modal__inner\" #modalInner>\n <ng-container *ngIf=\"content; else elseContent\">\n <ng-container *ngTemplateOutlet=\"content\"></ng-container>\n </ng-container>\n <ng-template #elseContent>\n <ng-content></ng-content>\n </ng-template>\n </div>\n</div>\n", components: [{ type: IconPlaceholderComponent, selector: "stream-icon-placeholder", inputs: ["icon", "size"] }], directives: [{ type: i2.TranslateDirective, selector: "[translate],[ngx-translate]", inputs: ["translate", "translateParams"] }, { type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i3.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet"] }] });
|
|
1922
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: ModalComponent, decorators: [{
|
|
1923
|
+
type: Component,
|
|
1924
|
+
args: [{
|
|
1925
|
+
selector: 'stream-modal',
|
|
1926
|
+
templateUrl: './modal.component.html',
|
|
1927
|
+
styles: [],
|
|
1928
|
+
}]
|
|
1929
|
+
}], ctorParameters: function () { return []; }, propDecorators: { isOpen: [{
|
|
1930
|
+
type: Input
|
|
1931
|
+
}], content: [{
|
|
1932
|
+
type: Input
|
|
1933
|
+
}], isOpenChange: [{
|
|
1934
|
+
type: Output
|
|
1935
|
+
}], innerContainer: [{
|
|
1936
|
+
type: ViewChild,
|
|
1937
|
+
args: ['modalInner']
|
|
1938
|
+
}] } });
|
|
1939
|
+
|
|
1645
1940
|
const textareaInjectionToken = new InjectionToken('textareaInjectionToken');
|
|
1646
1941
|
|
|
1647
1942
|
class TextareaDirective {
|
|
@@ -1668,10 +1963,6 @@ class TextareaDirective {
|
|
|
1668
1963
|
this.subscriptions.push(this.componentRef.instance.userMentions.subscribe((value) => this.userMentions.next(value)));
|
|
1669
1964
|
}
|
|
1670
1965
|
this.componentRef.instance.areMentionsEnabled = this.areMentionsEnabled;
|
|
1671
|
-
this.componentRef.instance.mentionAutocompleteItemTemplate =
|
|
1672
|
-
this.mentionAutocompleteItemTemplate;
|
|
1673
|
-
this.componentRef.instance.commandAutocompleteItemTemplate =
|
|
1674
|
-
this.commandAutocompleteItemTemplate;
|
|
1675
1966
|
this.componentRef.instance.mentionScope = this.mentionScope;
|
|
1676
1967
|
this.componentRef.instance.value = this.value;
|
|
1677
1968
|
}
|
|
@@ -1679,14 +1970,6 @@ class TextareaDirective {
|
|
|
1679
1970
|
if (changes.areMentionsEnabled) {
|
|
1680
1971
|
this.componentRef.instance.areMentionsEnabled = this.areMentionsEnabled;
|
|
1681
1972
|
}
|
|
1682
|
-
if (changes.mentionAutocompleteItemTemplate) {
|
|
1683
|
-
this.componentRef.instance.mentionAutocompleteItemTemplate =
|
|
1684
|
-
this.mentionAutocompleteItemTemplate;
|
|
1685
|
-
}
|
|
1686
|
-
if (changes.commandAutocompleteItemTemplate) {
|
|
1687
|
-
this.componentRef.instance.commandAutocompleteItemTemplate =
|
|
1688
|
-
this.commandAutocompleteItemTemplate;
|
|
1689
|
-
}
|
|
1690
1973
|
if (changes.mentionScope) {
|
|
1691
1974
|
this.componentRef.instance.mentionScope = this.mentionScope;
|
|
1692
1975
|
}
|
|
@@ -1702,7 +1985,7 @@ class TextareaDirective {
|
|
|
1702
1985
|
}
|
|
1703
1986
|
}
|
|
1704
1987
|
TextareaDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: TextareaDirective, deps: [{ token: i0.ViewContainerRef }], target: i0.ɵɵFactoryTarget.Directive });
|
|
1705
|
-
TextareaDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "12.2.5", type: TextareaDirective, selector: "[streamTextarea]", inputs: { componentRef: "componentRef", areMentionsEnabled: "areMentionsEnabled",
|
|
1988
|
+
TextareaDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "12.2.5", type: TextareaDirective, selector: "[streamTextarea]", inputs: { componentRef: "componentRef", areMentionsEnabled: "areMentionsEnabled", mentionScope: "mentionScope", value: "value" }, outputs: { valueChange: "valueChange", send: "send", userMentions: "userMentions" }, usesOnChanges: true, ngImport: i0 });
|
|
1706
1989
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: TextareaDirective, decorators: [{
|
|
1707
1990
|
type: Directive,
|
|
1708
1991
|
args: [{
|
|
@@ -1712,12 +1995,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImpor
|
|
|
1712
1995
|
type: Input
|
|
1713
1996
|
}], areMentionsEnabled: [{
|
|
1714
1997
|
type: Input
|
|
1715
|
-
}], mentionAutocompleteItemTemplate: [{
|
|
1716
|
-
type: Input
|
|
1717
1998
|
}], mentionScope: [{
|
|
1718
1999
|
type: Input
|
|
1719
|
-
}], commandAutocompleteItemTemplate: [{
|
|
1720
|
-
type: Input
|
|
1721
2000
|
}], value: [{
|
|
1722
2001
|
type: Input
|
|
1723
2002
|
}], valueChange: [{
|
|
@@ -1800,79 +2079,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImpor
|
|
|
1800
2079
|
}]
|
|
1801
2080
|
}], ctorParameters: function () { return []; } });
|
|
1802
2081
|
|
|
1803
|
-
/**
|
|
1804
|
-
* 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.
|
|
1805
|
-
*/
|
|
1806
|
-
class ModalComponent {
|
|
1807
|
-
constructor() {
|
|
1808
|
-
/**
|
|
1809
|
-
* If `true` the modal will be displayed, if `false` the modal will be hidden
|
|
1810
|
-
*/
|
|
1811
|
-
this.isOpen = false;
|
|
1812
|
-
/**
|
|
1813
|
-
* Emits `true` if the modal becomes visible, and `false` if the modal is closed.
|
|
1814
|
-
*/
|
|
1815
|
-
this.isOpenChange = new EventEmitter();
|
|
1816
|
-
this.watchForEscPress = (event) => {
|
|
1817
|
-
if (event.key === 'Escape') {
|
|
1818
|
-
this.close();
|
|
1819
|
-
}
|
|
1820
|
-
};
|
|
1821
|
-
this.stopWatchForEscPress = () => {
|
|
1822
|
-
window.removeEventListener('keyup', this.watchForEscPress);
|
|
1823
|
-
};
|
|
1824
|
-
this.watchForOutsideClicks = (event) => {
|
|
1825
|
-
var _a;
|
|
1826
|
-
if (!((_a = this.content) === null || _a === void 0 ? void 0 : _a.nativeElement.contains(event.target))) {
|
|
1827
|
-
this.close();
|
|
1828
|
-
}
|
|
1829
|
-
};
|
|
1830
|
-
}
|
|
1831
|
-
ngOnChanges(changes) {
|
|
1832
|
-
if (changes.isOpen) {
|
|
1833
|
-
if (this.isOpen) {
|
|
1834
|
-
window.addEventListener('keyup', this.watchForEscPress);
|
|
1835
|
-
setTimeout(() => window.addEventListener('click', this.watchForOutsideClicks), 0);
|
|
1836
|
-
}
|
|
1837
|
-
else {
|
|
1838
|
-
this.stopWatchForOutsideClicks();
|
|
1839
|
-
this.stopWatchForEscPress();
|
|
1840
|
-
}
|
|
1841
|
-
}
|
|
1842
|
-
}
|
|
1843
|
-
close() {
|
|
1844
|
-
this.isOpen = false;
|
|
1845
|
-
this.isOpenChange.emit(false);
|
|
1846
|
-
this.stopWatchForOutsideClicks();
|
|
1847
|
-
this.stopWatchForEscPress();
|
|
1848
|
-
}
|
|
1849
|
-
stopWatchForOutsideClicks() {
|
|
1850
|
-
window.removeEventListener('click', this.watchForOutsideClicks);
|
|
1851
|
-
}
|
|
1852
|
-
}
|
|
1853
|
-
ModalComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: ModalComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1854
|
-
ModalComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.5", type: ModalComponent, selector: "stream-modal", inputs: { isOpen: "isOpen" }, outputs: { isOpenChange: "isOpenChange" }, viewQueries: [{ propertyName: "content", first: true, predicate: ["content"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div\n data-testid=\"modal\"\n class=\"str-chat__modal str-chat__modal--{{ isOpen ? 'open' : 'close' }}\"\n>\n <div\n data-testid=\"close\"\n class=\"str-chat__modal__close-button\"\n (click)=\"close()\"\n (keyup.enter)=\"close()\"\n translate\n >\n streamChat.Close\n <stream-icon icon=\"close\"></stream-icon>\n </div>\n <div class=\"str-chat__modal__inner\" #content>\n <ng-content></ng-content>\n </div>\n</div>\n", components: [{ type: IconComponent, selector: "stream-icon", inputs: ["icon", "size"] }], directives: [{ type: i2.TranslateDirective, selector: "[translate],[ngx-translate]", inputs: ["translate", "translateParams"] }] });
|
|
1855
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: ModalComponent, decorators: [{
|
|
1856
|
-
type: Component,
|
|
1857
|
-
args: [{
|
|
1858
|
-
selector: 'stream-modal',
|
|
1859
|
-
templateUrl: './modal.component.html',
|
|
1860
|
-
styles: [],
|
|
1861
|
-
}]
|
|
1862
|
-
}], ctorParameters: function () { return []; }, propDecorators: { isOpen: [{
|
|
1863
|
-
type: Input
|
|
1864
|
-
}], isOpenChange: [{
|
|
1865
|
-
type: Output
|
|
1866
|
-
}], content: [{
|
|
1867
|
-
type: ViewChild,
|
|
1868
|
-
args: ['content']
|
|
1869
|
-
}] } });
|
|
1870
|
-
|
|
1871
2082
|
/**
|
|
1872
2083
|
* The `AttachmentList` compontent displays the attachments of a message
|
|
1873
2084
|
*/
|
|
1874
2085
|
class AttachmentListComponent {
|
|
1875
|
-
constructor(imageLoadService, channelService) {
|
|
2086
|
+
constructor(customTemplatesService, imageLoadService, channelService) {
|
|
2087
|
+
this.customTemplatesService = customTemplatesService;
|
|
1876
2088
|
this.imageLoadService = imageLoadService;
|
|
1877
2089
|
this.channelService = channelService;
|
|
1878
2090
|
/**
|
|
@@ -1918,6 +2130,13 @@ class AttachmentListComponent {
|
|
|
1918
2130
|
getFileSize(attachment) {
|
|
1919
2131
|
return prettybytes(Number(attachment.file_size));
|
|
1920
2132
|
}
|
|
2133
|
+
getModalContext() {
|
|
2134
|
+
return {
|
|
2135
|
+
isOpen: this.imagesToView && this.imagesToView.length > 0,
|
|
2136
|
+
isOpenChangeHandler: (isOpen) => (isOpen ? null : this.closeImageModal()),
|
|
2137
|
+
content: this.modalContent,
|
|
2138
|
+
};
|
|
2139
|
+
}
|
|
1921
2140
|
trimUrl(url) {
|
|
1922
2141
|
if (url !== undefined && url !== null) {
|
|
1923
2142
|
const [trimmedUrl] = url
|
|
@@ -1939,9 +2158,6 @@ class AttachmentListComponent {
|
|
|
1939
2158
|
this.imagesToView = attachments;
|
|
1940
2159
|
this.imagesToViewCurrentIndex = selectedIndex;
|
|
1941
2160
|
}
|
|
1942
|
-
closeImageModal() {
|
|
1943
|
-
this.imagesToView = [];
|
|
1944
|
-
}
|
|
1945
2161
|
stepImages(dir) {
|
|
1946
2162
|
this.imagesToViewCurrentIndex += dir * 1;
|
|
1947
2163
|
}
|
|
@@ -1962,9 +2178,12 @@ class AttachmentListComponent {
|
|
|
1962
2178
|
},
|
|
1963
2179
|
];
|
|
1964
2180
|
}
|
|
2181
|
+
closeImageModal() {
|
|
2182
|
+
this.imagesToView = [];
|
|
2183
|
+
}
|
|
1965
2184
|
}
|
|
1966
|
-
AttachmentListComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: AttachmentListComponent, deps: [{ token: ImageLoadService }, { token: ChannelService }], target: i0.ɵɵFactoryTarget.Component });
|
|
1967
|
-
AttachmentListComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.5", type: AttachmentListComponent, selector: "stream-attachment-list", inputs: { messageId: "messageId", attachments: "attachments" }, usesOnChanges: true, ngImport: i0, template: "<ng-container *ngFor=\"let attachment of orderedAttachments; trackBy: trackById\">\n <div\n data-testclass=\"attachment-container\"\n class=\"str-chat__message-attachment str-chat__message-attachment--{{\n attachment.type\n }}\"\n [class.str-chat__message-attachment--card]=\"isCard(attachment)\"\n [class.str-chat-angular__message-attachment-file-single]=\"\n isFile(attachment)\n \"\n >\n <img\n *ngIf=\"isImage(attachment)\"\n class=\"str-chat__message-attachment--img\"\n data-testclass=\"image\"\n [src]=\"attachment.img_url || attachment.thumb_url || attachment.image_url\"\n [alt]=\"attachment?.fallback\"\n (load)=\"imageLoaded()\"\n (click)=\"openImageModal([attachment])\"\n (keyup.enter)=\"openImageModal([attachment])\"\n />\n <div\n class=\"str-chat__gallery\"\n data-testid=\"image-gallery\"\n *ngIf=\"isGallery(attachment)\"\n [class.str-chat__gallery--square]=\"(attachment?.images)!.length > 3\"\n >\n <ng-container\n *ngFor=\"\n let galleryImage of attachment.images;\n let index = index;\n let isLast = last;\n trackBy: trackByImageUrl\n \"\n >\n <button\n *ngIf=\"index < 3 || (index === 3 && isLast)\"\n class=\"str-chat__gallery-image\"\n data-testclass=\"gallery-image\"\n (click)=\"openImageModal(attachment.images!, index)\"\n (keyup.enter)=\"openImageModal(attachment.images!, index)\"\n >\n <img\n [src]=\"\n galleryImage.img_url ||\n galleryImage.thumb_url ||\n galleryImage.image_url\n \"\n [alt]=\"galleryImage.fallback\"\n (load)=\"imageLoaded()\"\n />\n </button>\n <button\n *ngIf=\"index === 3 && !isLast\"\n class=\"str-chat__gallery-placeholder\"\n data-testclass=\"gallery-image\"\n (click)=\"openImageModal(attachment.images!, index)\"\n (keyup.enter)=\"openImageModal(attachment.images!, index)\"\n [ngStyle]=\"{\n 'background-image':\n 'url(' +\n (galleryImage.img_url ||\n galleryImage.thumb_url ||\n galleryImage.image_url) +\n ')'\n }\"\n >\n <p\n [innerHTML]=\"\n 'streamChat.{{ imageCount }} more'\n | translate: { imageCount: attachment!.images!.length - 4 }\n \"\n ></p>\n </button>\n </ng-container>\n </div>\n <div\n *ngIf=\"isFile(attachment)\"\n class=\"\n str-chat__message-attachment-file--item\n str-chat-angular__message-attachment-file-single\n \"\n >\n <stream-icon
|
|
2185
|
+
AttachmentListComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: AttachmentListComponent, deps: [{ token: CustomTemplatesService }, { token: ImageLoadService }, { token: ChannelService }], target: i0.ɵɵFactoryTarget.Component });
|
|
2186
|
+
AttachmentListComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.5", type: AttachmentListComponent, selector: "stream-attachment-list", inputs: { messageId: "messageId", attachments: "attachments" }, viewQueries: [{ propertyName: "modalContent", first: true, predicate: ["modalContent"], descendants: true, static: true }], usesOnChanges: true, ngImport: i0, template: "<ng-container *ngFor=\"let attachment of orderedAttachments; trackBy: trackById\">\n <div\n data-testclass=\"attachment-container\"\n class=\"str-chat__message-attachment str-chat__message-attachment--{{\n attachment.type\n }}\"\n [class.str-chat__message-attachment--card]=\"isCard(attachment)\"\n [class.str-chat-angular__message-attachment-file-single]=\"\n isFile(attachment)\n \"\n >\n <img\n *ngIf=\"isImage(attachment)\"\n class=\"str-chat__message-attachment--img\"\n data-testclass=\"image\"\n [src]=\"attachment.img_url || attachment.thumb_url || attachment.image_url\"\n [alt]=\"attachment?.fallback\"\n (load)=\"imageLoaded()\"\n (click)=\"openImageModal([attachment])\"\n (keyup.enter)=\"openImageModal([attachment])\"\n />\n <div\n class=\"str-chat__gallery\"\n data-testid=\"image-gallery\"\n *ngIf=\"isGallery(attachment)\"\n [class.str-chat__gallery--square]=\"(attachment?.images)!.length > 3\"\n >\n <ng-container\n *ngFor=\"\n let galleryImage of attachment.images;\n let index = index;\n let isLast = last;\n trackBy: trackByImageUrl\n \"\n >\n <button\n *ngIf=\"index < 3 || (index === 3 && isLast)\"\n class=\"str-chat__gallery-image\"\n data-testclass=\"gallery-image\"\n (click)=\"openImageModal(attachment.images!, index)\"\n (keyup.enter)=\"openImageModal(attachment.images!, index)\"\n >\n <img\n [src]=\"\n galleryImage.img_url ||\n galleryImage.thumb_url ||\n galleryImage.image_url\n \"\n [alt]=\"galleryImage.fallback\"\n (load)=\"imageLoaded()\"\n />\n </button>\n <button\n *ngIf=\"index === 3 && !isLast\"\n class=\"str-chat__gallery-placeholder\"\n data-testclass=\"gallery-image\"\n (click)=\"openImageModal(attachment.images!, index)\"\n (keyup.enter)=\"openImageModal(attachment.images!, index)\"\n [ngStyle]=\"{\n 'background-image':\n 'url(' +\n (galleryImage.img_url ||\n galleryImage.thumb_url ||\n galleryImage.image_url) +\n ')'\n }\"\n >\n <p\n [innerHTML]=\"\n 'streamChat.{{ imageCount }} more'\n | translate: { imageCount: attachment!.images!.length - 4 }\n \"\n ></p>\n </button>\n </ng-container>\n </div>\n <div\n *ngIf=\"isFile(attachment)\"\n class=\"\n str-chat__message-attachment-file--item\n str-chat-angular__message-attachment-file-single\n \"\n >\n <stream-icon-placeholder\n icon=\"file\"\n [size]=\"30\"\n ></stream-icon-placeholder>\n <div class=\"str-chat__message-attachment-file--item-text\">\n <a\n data-testclass=\"file-link\"\n download\n href=\"{{ attachment.asset_url }}\"\n target=\"_blank\"\n >\n {{ attachment.title }}\n </a>\n <span data-testclass=\"size\" *ngIf=\"hasFileSize(attachment)\">{{\n getFileSize(attachment)\n }}</span>\n </div>\n </div>\n <div\n *ngIf=\"isCard(attachment)\"\n class=\"str-chat__message-attachment-card str-chat__message-attachment-card--{{\n attachment.type\n }}\"\n >\n <div\n *ngIf=\"attachment.image_url || attachment.thumb_url\"\n class=\"str-chat__message-attachment-card--header\"\n >\n <img\n data-testclass=\"card-img\"\n alt=\"{{ attachment.image_url || attachment.thumb_url }}\"\n src=\"{{ attachment.image_url || attachment.thumb_url }}\"\n />\n </div>\n <div class=\"str-chat__message-attachment-card--content\">\n <div class=\"str-chat__message-attachment-card--flex\">\n <div\n *ngIf=\"attachment.title\"\n data-testclass=\"card-title\"\n class=\"str-chat__message-attachment-card--title\"\n >\n {{ attachment.title }}\n </div>\n <div\n *ngIf=\"attachment.text\"\n class=\"str-chat__message-attachment-card--text\"\n data-testclass=\"card-text\"\n >\n {{ attachment.text }}\n </div>\n <a\n class=\"str-chat__message-attachment-card--url\"\n *ngIf=\"attachment.title_link || attachment.og_scrape_url\"\n data-testclass=\"url-link\"\n noopener\n noreferrer\n href=\"{{ attachment.title_link || attachment.og_scrape_url }}\"\n target=\"_blank\"\n >\n {{ trimUrl(attachment.title_link || attachment.og_scrape_url) }}\n </a>\n </div>\n </div>\n </div>\n <div\n class=\"str-chat__message-attachment-actions\"\n *ngIf=\"attachment.actions && attachment.actions.length > 0\"\n >\n <div class=\"str-chat__message-attachment-actions-form\">\n <button\n *ngFor=\"let action of attachment.actions; trackBy: trackByActionValue\"\n class=\"str-chat__message-attachment-actions-button str-chat__message-attachment-actions-button--{{\n action.style\n }}\"\n data-testclass=\"attachment-action\"\n (click)=\"sendAction(action)\"\n (keyup.enter)=\"sendAction(action)\"\n >\n {{ action.text }}\n </button>\n </div>\n </div>\n </div>\n</ng-container>\n\n<ng-container *ngIf=\"imagesToView && imagesToView.length > 0\">\n <ng-container\n *ngTemplateOutlet=\"\n (customTemplatesService.modalTemplate$ | async) || defaultModal;\n context: getModalContext()\n \"\n ></ng-container>\n</ng-container>\n\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 (isOpenChange)=\"isOpenChangeHandler($event)\"\n [content]=\"content\"\n >\n </stream-modal>\n</ng-template>\n\n<ng-template #modalContent>\n <div class=\"stream-chat-angular__image-modal\">\n <button\n class=\"stream-chat-angular__image-modal-stepper\"\n [ngStyle]=\"{\n visibility: isImageModalPrevButtonVisible ? 'visible' : 'hidden'\n }\"\n data-testid=\"image-modal-prev\"\n type=\"button\"\n (click)=\"stepImages(-1)\"\n (keyup.enter)=\"stepImages(-1)\"\n >\n <stream-icon-placeholder icon=\"arrow-left\"></stream-icon-placeholder>\n </button>\n <img\n class=\"stream-chat-angular__image-modal-image\"\n data-testid=\"modal-image\"\n [src]=\"\n imagesToView[imagesToViewCurrentIndex].img_url ||\n imagesToView[imagesToViewCurrentIndex].thumb_url ||\n imagesToView[imagesToViewCurrentIndex].image_url\n \"\n [alt]=\"imagesToView[imagesToViewCurrentIndex].fallback\"\n />\n <button\n class=\"stream-chat-angular__image-modal-stepper\"\n type=\"button\"\n [ngStyle]=\"{\n visibility: isImageModalNextButtonVisible ? 'visible' : 'hidden'\n }\"\n data-testid=\"image-modal-next\"\n (click)=\"stepImages(1)\"\n (keyup.enter)=\"stepImages(1)\"\n >\n <stream-icon-placeholder icon=\"arrow-right\"></stream-icon-placeholder>\n </button>\n </div>\n</ng-template>\n", components: [{ type: IconPlaceholderComponent, selector: "stream-icon-placeholder", inputs: ["icon", "size"] }, { type: ModalComponent, selector: "stream-modal", inputs: ["isOpen", "content"], outputs: ["isOpenChange"] }], directives: [{ type: i3.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i3.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { type: i3.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet"] }], pipes: { "translate": i2.TranslatePipe, "async": i3.AsyncPipe } });
|
|
1968
2187
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: AttachmentListComponent, decorators: [{
|
|
1969
2188
|
type: Component,
|
|
1970
2189
|
args: [{
|
|
@@ -1972,36 +2191,41 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImpor
|
|
|
1972
2191
|
templateUrl: './attachment-list.component.html',
|
|
1973
2192
|
styles: [],
|
|
1974
2193
|
}]
|
|
1975
|
-
}], ctorParameters: function () { return [{ type: ImageLoadService }, { type: ChannelService }]; }, propDecorators: { messageId: [{
|
|
2194
|
+
}], ctorParameters: function () { return [{ type: CustomTemplatesService }, { type: ImageLoadService }, { type: ChannelService }]; }, propDecorators: { messageId: [{
|
|
1976
2195
|
type: Input
|
|
1977
2196
|
}], attachments: [{
|
|
1978
2197
|
type: Input
|
|
2198
|
+
}], modalContent: [{
|
|
2199
|
+
type: ViewChild,
|
|
2200
|
+
args: ['modalContent', { static: true }]
|
|
1979
2201
|
}] } });
|
|
1980
2202
|
|
|
1981
2203
|
/**
|
|
1982
2204
|
* The `AttachmentPreviewList` compontent displays a preview of the attachments uploaded to a message. Users can delete attachments using the preview component, or retry upload if it failed previously.
|
|
1983
2205
|
*/
|
|
1984
2206
|
class AttachmentPreviewListComponent {
|
|
1985
|
-
constructor(
|
|
1986
|
-
|
|
1987
|
-
|
|
2207
|
+
constructor() {
|
|
2208
|
+
/**
|
|
2209
|
+
* An output to notify the parent component if the user tries to retry a failed upload
|
|
2210
|
+
*/
|
|
2211
|
+
this.retryAttachmentUpload = new EventEmitter();
|
|
2212
|
+
/**
|
|
2213
|
+
* An output to notify the parent component if the user wants to delete a file
|
|
2214
|
+
*/
|
|
2215
|
+
this.deleteAttachment = new EventEmitter();
|
|
1988
2216
|
}
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
yield this.attachmentService.retryAttachmentUpload(file);
|
|
1992
|
-
});
|
|
2217
|
+
attachmentUploadRetried(file) {
|
|
2218
|
+
this.retryAttachmentUpload.emit(file);
|
|
1993
2219
|
}
|
|
1994
|
-
|
|
1995
|
-
|
|
1996
|
-
yield this.attachmentService.deleteAttachment(upload);
|
|
1997
|
-
});
|
|
2220
|
+
attachmentDeleted(upload) {
|
|
2221
|
+
this.deleteAttachment.emit(upload);
|
|
1998
2222
|
}
|
|
1999
2223
|
trackByFile(_, item) {
|
|
2000
2224
|
return item.file;
|
|
2001
2225
|
}
|
|
2002
2226
|
}
|
|
2003
|
-
AttachmentPreviewListComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: AttachmentPreviewListComponent, deps: [
|
|
2004
|
-
AttachmentPreviewListComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.5", type: AttachmentPreviewListComponent, selector: "stream-attachment-preview-list", ngImport: i0, template: "<div class=\"rfu-image-previewer\" *ngIf=\"(attachmentUploads$ | async)?.length\">\n <ng-container\n *ngFor=\"\n let attachmentUpload of attachmentUploads$ | async;\n trackBy: trackByFile\n \"\n >\n <div\n *ngIf=\"attachmentUpload.type === 'image'\"\n class=\"rfu-image-previewer__image\"\n [class.rfu-image-previewer__image--loaded]=\"\n attachmentUpload.state === 'success'\n \"\n data-testclass=\"attachment-image-preview\"\n >\n <div\n *ngIf=\"attachmentUpload.state === 'error'\"\n class=\"rfu-image-previewer__retry\"\n (click)=\"
|
|
2227
|
+
AttachmentPreviewListComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: AttachmentPreviewListComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2228
|
+
AttachmentPreviewListComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.5", type: AttachmentPreviewListComponent, selector: "stream-attachment-preview-list", inputs: { attachmentUploads$: "attachmentUploads$" }, outputs: { retryAttachmentUpload: "retryAttachmentUpload", deleteAttachment: "deleteAttachment" }, ngImport: i0, template: "<div class=\"rfu-image-previewer\" *ngIf=\"(attachmentUploads$ | async)?.length\">\n <ng-container\n *ngFor=\"\n let attachmentUpload of attachmentUploads$ | async;\n trackBy: trackByFile\n \"\n >\n <div\n *ngIf=\"attachmentUpload.type === 'image'\"\n class=\"rfu-image-previewer__image\"\n [class.rfu-image-previewer__image--loaded]=\"\n attachmentUpload.state === 'success'\n \"\n data-testclass=\"attachment-image-preview\"\n >\n <div\n *ngIf=\"attachmentUpload.state === 'error'\"\n class=\"rfu-image-previewer__retry\"\n (click)=\"attachmentUploadRetried(attachmentUpload.file)\"\n (keyup.enter)=\"attachmentUploadRetried(attachmentUpload.file)\"\n data-testclass=\"upload-error\"\n >\n <stream-icon-placeholder icon=\"retry\"></stream-icon-placeholder>\n </div>\n <div class=\"rfu-thumbnail__wrapper\" style=\"width: 100; height: 100\">\n <div class=\"rfu-thumbnail__overlay\">\n <div\n class=\"rfu-icon-button\"\n data-testclass=\"delete-attachment\"\n role=\"button\"\n (click)=\"attachmentDeleted(attachmentUpload)\"\n (keyup.enter)=\"attachmentDeleted(attachmentUpload)\"\n >\n <stream-icon-placeholder icon=\"close\"></stream-icon-placeholder>\n </div>\n </div>\n <img\n *ngIf=\"attachmentUpload.url || attachmentUpload.previewUri\"\n src=\"{{\n attachmentUpload.url\n ? attachmentUpload.url\n : attachmentUpload.previewUri\n }}\"\n alt=\"attachmentUpload.file.name\"\n class=\"rfu-thumbnail__image\"\n data-testclass=\"attachment-image\"\n />\n </div>\n <stream-loading-indicator-placeholder\n data-testclass=\"loading-indicator\"\n color=\"rgba(255,255,255,0.7)\"\n *ngIf=\"attachmentUpload.state === 'uploading'\"\n ></stream-loading-indicator-placeholder>\n </div>\n <div\n class=\"rfu-file-previewer\"\n *ngIf=\"attachmentUpload.type === 'file'\"\n data-testclass=\"attachment-file-preview\"\n >\n <ol>\n <li\n class=\"rfu-file-previewer__file\"\n [class.rfu-file-previewer__file--uploading]=\"\n attachmentUpload.state === 'uploading'\n \"\n [class.rfu-file-previewer__file--failed]=\"\n attachmentUpload.state === 'error'\n \"\n >\n <stream-icon-placeholder icon=\"file\"></stream-icon-placeholder>\n\n <a\n data-testclass=\"file-download-link\"\n href=\"{{ attachmentUpload.url }}\"\n (click)=\"attachmentUpload.url ? null : $event.preventDefault()\"\n (keyup.enter)=\"\n attachmentUpload.url ? null : $event.preventDefault()\n \"\n download\n >\n {{ attachmentUpload.file.name }}\n <ng-container *ngIf=\"attachmentUpload.state === 'error'\">\n <div\n data-testclass=\"file-upload-retry\"\n class=\"rfu-file-previewer__failed\"\n (click)=\"attachmentUploadRetried(attachmentUpload.file)\"\n (keyup.enter)=\"attachmentUploadRetried(attachmentUpload.file)\"\n translate\n >\n streamChat.failed\n </div>\n <div\n class=\"rfu-file-previewer__retry\"\n (click)=\"attachmentUploadRetried(attachmentUpload.file)\"\n (keyup.enter)=\"attachmentUploadRetried(attachmentUpload.file)\"\n translate\n >\n streamChat.retry\n </div>\n </ng-container>\n </a>\n\n <span\n data-testclass=\"file-delete\"\n class=\"rfu-file-previewer__close-button\"\n (click)=\"attachmentDeleted(attachmentUpload)\"\n (keyup.enter)=\"attachmentDeleted(attachmentUpload)\"\n >\n \u2718\n </span>\n <div\n *ngIf=\"attachmentUpload.state === 'uploading'\"\n class=\"rfu-file-previewer__loading-indicator\"\n >\n <stream-loading-indicator-placeholder></stream-loading-indicator-placeholder>\n </div>\n </li>\n </ol>\n </div>\n </ng-container>\n</div>\n", components: [{ type: IconPlaceholderComponent, selector: "stream-icon-placeholder", inputs: ["icon", "size"] }, { type: LoadingIndicatorPlaceholderComponent, selector: "stream-loading-indicator-placeholder", inputs: ["size", "color"] }], directives: [{ type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i3.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i2.TranslateDirective, selector: "[translate],[ngx-translate]", inputs: ["translate", "translateParams"] }], pipes: { "async": i3.AsyncPipe } });
|
|
2005
2229
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: AttachmentPreviewListComponent, decorators: [{
|
|
2006
2230
|
type: Component,
|
|
2007
2231
|
args: [{
|
|
@@ -2009,13 +2233,19 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImpor
|
|
|
2009
2233
|
templateUrl: './attachment-preview-list.component.html',
|
|
2010
2234
|
styles: [],
|
|
2011
2235
|
}]
|
|
2012
|
-
}], ctorParameters: function () { return [
|
|
2236
|
+
}], ctorParameters: function () { return []; }, propDecorators: { attachmentUploads$: [{
|
|
2237
|
+
type: Input
|
|
2238
|
+
}], retryAttachmentUpload: [{
|
|
2239
|
+
type: Output
|
|
2240
|
+
}], deleteAttachment: [{
|
|
2241
|
+
type: Output
|
|
2242
|
+
}] } });
|
|
2013
2243
|
|
|
2014
2244
|
/**
|
|
2015
2245
|
* The `MessageInput` component displays an input where users can type their messages and upload files, and sends the message to the active channel. The component can be used to compose new messages or update existing ones. To send messages, the chat user needs to have the necessary [channel capability](https://getstream.io/chat/docs/javascript/channel_capabilities/?language=javascript).
|
|
2016
2246
|
*/
|
|
2017
2247
|
class MessageInputComponent {
|
|
2018
|
-
constructor(channelService, notificationService, attachmentService, configService, textareaType, componentFactoryResolver, cdRef, chatClient, emojiInputService) {
|
|
2248
|
+
constructor(channelService, notificationService, attachmentService, configService, textareaType, componentFactoryResolver, cdRef, chatClient, emojiInputService, customTemplatesService) {
|
|
2019
2249
|
this.channelService = channelService;
|
|
2020
2250
|
this.notificationService = notificationService;
|
|
2021
2251
|
this.attachmentService = attachmentService;
|
|
@@ -2025,6 +2255,7 @@ class MessageInputComponent {
|
|
|
2025
2255
|
this.cdRef = cdRef;
|
|
2026
2256
|
this.chatClient = chatClient;
|
|
2027
2257
|
this.emojiInputService = emojiInputService;
|
|
2258
|
+
this.customTemplatesService = customTemplatesService;
|
|
2028
2259
|
/**
|
|
2029
2260
|
* Determines if the message is being dispalyed in a channel or in a [thread](https://getstream.io/chat/docs/javascript/threads/?language=javascript).
|
|
2030
2261
|
*/
|
|
@@ -2069,16 +2300,10 @@ class MessageInputComponent {
|
|
|
2069
2300
|
}));
|
|
2070
2301
|
this.attachmentUploads$ = this.attachmentService.attachmentUploads$;
|
|
2071
2302
|
this.isFileUploadEnabled = this.configService.isFileUploadEnabled;
|
|
2072
|
-
this.acceptedFileTypes = this.configService.acceptedFileTypes;
|
|
2073
2303
|
this.isMultipleFileUploadEnabled =
|
|
2074
2304
|
this.configService.isMultipleFileUploadEnabled;
|
|
2075
2305
|
this.areMentionsEnabled = this.configService.areMentionsEnabled;
|
|
2076
|
-
this.mentionAutocompleteItemTemplate =
|
|
2077
|
-
this.configService.mentionAutocompleteItemTemplate;
|
|
2078
2306
|
this.mentionScope = this.configService.mentionScope;
|
|
2079
|
-
this.commandAutocompleteItemTemplate =
|
|
2080
|
-
this.configService.commandAutocompleteItemTemplate;
|
|
2081
|
-
this.emojiPickerTemplate = this.configService.emojiPickerTemplate;
|
|
2082
2307
|
this.subscriptions.push(this.typingStart$.subscribe(() => void this.channelService.typingStarted(this.parentMessageId)));
|
|
2083
2308
|
this.subscriptions.push(combineLatest([
|
|
2084
2309
|
this.channelService.latestMessageDateByUserByChannels$,
|
|
@@ -2101,6 +2326,16 @@ class MessageInputComponent {
|
|
|
2101
2326
|
}
|
|
2102
2327
|
}));
|
|
2103
2328
|
}
|
|
2329
|
+
ngOnInit() {
|
|
2330
|
+
this.subscriptions.push(this.customTemplatesService.emojiPickerTemplate$.subscribe((template) => {
|
|
2331
|
+
this.emojiPickerTemplate = template;
|
|
2332
|
+
this.cdRef.detectChanges();
|
|
2333
|
+
}));
|
|
2334
|
+
this.subscriptions.push(this.customTemplatesService.attachmentPreviewListTemplate$.subscribe((template) => {
|
|
2335
|
+
this.attachmentPreviewListTemplate = template;
|
|
2336
|
+
this.cdRef.detectChanges();
|
|
2337
|
+
}));
|
|
2338
|
+
}
|
|
2104
2339
|
ngAfterViewInit() {
|
|
2105
2340
|
this.isViewInited = true;
|
|
2106
2341
|
this.initTextarea();
|
|
@@ -2116,9 +2351,6 @@ class MessageInputComponent {
|
|
|
2116
2351
|
if (changes.isFileUploadEnabled) {
|
|
2117
2352
|
this.configService.isFileUploadEnabled = this.isFileUploadEnabled;
|
|
2118
2353
|
}
|
|
2119
|
-
if (changes.acceptedFileTypes) {
|
|
2120
|
-
this.configService.acceptedFileTypes = this.acceptedFileTypes;
|
|
2121
|
-
}
|
|
2122
2354
|
if (changes.isMultipleFileUploadEnabled) {
|
|
2123
2355
|
this.configService.isMultipleFileUploadEnabled =
|
|
2124
2356
|
this.isMultipleFileUploadEnabled;
|
|
@@ -2126,25 +2358,25 @@ class MessageInputComponent {
|
|
|
2126
2358
|
if (changes.areMentionsEnabled) {
|
|
2127
2359
|
this.configService.areMentionsEnabled = this.areMentionsEnabled;
|
|
2128
2360
|
}
|
|
2129
|
-
if (changes.mentionAutocompleteItemTemplate) {
|
|
2130
|
-
this.configService.mentionAutocompleteItemTemplate =
|
|
2131
|
-
this.mentionAutocompleteItemTemplate;
|
|
2132
|
-
}
|
|
2133
|
-
if (changes.commandAutocompleteItemTemplate) {
|
|
2134
|
-
this.configService.commandAutocompleteItemTemplate =
|
|
2135
|
-
this.commandAutocompleteItemTemplate;
|
|
2136
|
-
}
|
|
2137
2361
|
if (changes.mentionScope) {
|
|
2138
2362
|
this.configService.mentionScope = this.mentionScope;
|
|
2139
2363
|
}
|
|
2140
|
-
if (changes.emojiPickerTemplate) {
|
|
2141
|
-
this.configService.emojiPickerTemplate = this.emojiPickerTemplate;
|
|
2142
|
-
}
|
|
2143
2364
|
if (changes.mode) {
|
|
2144
2365
|
this.setCanSendMessages();
|
|
2145
2366
|
}
|
|
2367
|
+
if (changes.sendMessage$) {
|
|
2368
|
+
if (this.sendMessageSubcription) {
|
|
2369
|
+
this.sendMessageSubcription.unsubscribe();
|
|
2370
|
+
}
|
|
2371
|
+
if (this.sendMessage$) {
|
|
2372
|
+
this.sendMessageSubcription = this.sendMessage$.subscribe(() => void this.messageSent());
|
|
2373
|
+
}
|
|
2374
|
+
}
|
|
2146
2375
|
}
|
|
2147
2376
|
ngOnDestroy() {
|
|
2377
|
+
if (this.sendMessageSubcription) {
|
|
2378
|
+
this.sendMessageSubcription.unsubscribe();
|
|
2379
|
+
}
|
|
2148
2380
|
this.subscriptions.forEach((s) => s.unsubscribe());
|
|
2149
2381
|
}
|
|
2150
2382
|
messageSent() {
|
|
@@ -2196,10 +2428,6 @@ class MessageInputComponent {
|
|
|
2196
2428
|
get containsLinks() {
|
|
2197
2429
|
return /(?:(?:https?|ftp):\/\/)?[\w/\-?=%.]+\.[\w/\-&?=%.]+/.test(this.textareaValue);
|
|
2198
2430
|
}
|
|
2199
|
-
get accept() {
|
|
2200
|
-
var _a;
|
|
2201
|
-
return this.acceptedFileTypes ? (_a = this.acceptedFileTypes) === null || _a === void 0 ? void 0 : _a.join(',') : '';
|
|
2202
|
-
}
|
|
2203
2431
|
get quotedMessageAttachments() {
|
|
2204
2432
|
var _a;
|
|
2205
2433
|
const originalAttachments = (_a = this.quotedMessage) === null || _a === void 0 ? void 0 : _a.attachments;
|
|
@@ -2230,6 +2458,24 @@ class MessageInputComponent {
|
|
|
2230
2458
|
deselectMessageToQuote() {
|
|
2231
2459
|
this.channelService.selectMessageToQuote(undefined);
|
|
2232
2460
|
}
|
|
2461
|
+
getEmojiPickerContext() {
|
|
2462
|
+
return {
|
|
2463
|
+
emojiInput$: this.emojiInputService.emojiInput$,
|
|
2464
|
+
};
|
|
2465
|
+
}
|
|
2466
|
+
getAttachmentPreviewListContext() {
|
|
2467
|
+
return {
|
|
2468
|
+
attachmentUploads$: this.attachmentService.attachmentUploads$,
|
|
2469
|
+
deleteUploadHandler: this.deleteUpload.bind(this),
|
|
2470
|
+
retryUploadHandler: this.retryUpload.bind(this),
|
|
2471
|
+
};
|
|
2472
|
+
}
|
|
2473
|
+
deleteUpload(upload) {
|
|
2474
|
+
void this.attachmentService.deleteAttachment(upload);
|
|
2475
|
+
}
|
|
2476
|
+
retryUpload(file) {
|
|
2477
|
+
void this.attachmentService.retryAttachmentUpload(file);
|
|
2478
|
+
}
|
|
2233
2479
|
clearFileInput() {
|
|
2234
2480
|
this.fileInput.nativeElement.value = '';
|
|
2235
2481
|
}
|
|
@@ -2247,7 +2493,7 @@ class MessageInputComponent {
|
|
|
2247
2493
|
}
|
|
2248
2494
|
areAttachemntsValid(fileList) {
|
|
2249
2495
|
return __awaiter(this, void 0, void 0, function* () {
|
|
2250
|
-
if (!fileList
|
|
2496
|
+
if (!fileList) {
|
|
2251
2497
|
return true;
|
|
2252
2498
|
}
|
|
2253
2499
|
if (!this.appSettings) {
|
|
@@ -2336,8 +2582,8 @@ class MessageInputComponent {
|
|
|
2336
2582
|
setTimeout(() => this.initTextarea());
|
|
2337
2583
|
}
|
|
2338
2584
|
}
|
|
2339
|
-
MessageInputComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: MessageInputComponent, deps: [{ token: ChannelService }, { token: NotificationService }, { token: AttachmentService }, { token: MessageInputConfigService }, { token: textareaInjectionToken }, { token: i0.ComponentFactoryResolver }, { token: i0.ChangeDetectorRef }, { token: ChatClientService }, { token: EmojiInputService }], target: i0.ɵɵFactoryTarget.Component });
|
|
2340
|
-
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",
|
|
2585
|
+
MessageInputComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: MessageInputComponent, deps: [{ token: ChannelService }, { token: NotificationService }, { token: AttachmentService }, { token: MessageInputConfigService }, { token: textareaInjectionToken }, { token: i0.ComponentFactoryResolver }, { token: i0.ChangeDetectorRef }, { token: ChatClientService }, { token: EmojiInputService }, { token: CustomTemplatesService }], target: i0.ɵɵFactoryTarget.Component });
|
|
2586
|
+
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", mode: "mode", isMultipleFileUploadEnabled: "isMultipleFileUploadEnabled", message: "message", sendMessage$: "sendMessage$" }, outputs: { messageUpdate: "messageUpdate" }, providers: [AttachmentService, EmojiInputService], viewQueries: [{ propertyName: "fileInput", first: true, predicate: ["fileInput"], descendants: true }, { propertyName: "textareaAnchor", first: true, predicate: TextareaDirective, descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div\n class=\"{{\n mode === 'main' ? 'str-chat__input-flat' : 'str-chat__small-message-input'\n }}\"\n [class.str-chat__input-flat-has-attachments]=\"\n (attachmentUploads$ | async)!.length > 0\n \"\n [class.str-chat__input-flat-quoted]=\"!!quotedMessage\"\n>\n <div\n data-testid=\"quoted-message-container\"\n class=\"quoted-message-preview\"\n *ngIf=\"quotedMessage\"\n >\n <div class=\"quoted-message-preview-header\">\n <div>{{ \"streamChat.Reply to Message\" | translate }}</div>\n <button\n class=\"str-chat__square-button\"\n data-testid=\"remove-quote\"\n (click)=\"deselectMessageToQuote()\"\n (keyup.enter)=\"deselectMessageToQuote()\"\n >\n <stream-icon-placeholder\n icon=\"close-no-outline\"\n style=\"font-size: 10px; line-height: 10px\"\n ></stream-icon-placeholder>\n </button>\n </div>\n <div class=\"quoted-message-preview-content\">\n <stream-avatar-placeholder\n data-testid=\"qouted-message-avatar\"\n class=\"str-chat-angular__avatar-host\"\n [imageUrl]=\"quotedMessage?.user?.image\"\n [name]=\"quotedMessage?.user?.name || quotedMessage?.user?.id\"\n [size]=\"20\"\n ></stream-avatar-placeholder>\n <div class=\"quoted-message-preview-content-inner\">\n <stream-attachment-list\n *ngIf=\"\n quotedMessage?.attachments && quotedMessage?.attachments?.length\n \"\n [attachments]=\"quotedMessageAttachments\"\n [messageId]=\"quotedMessage?.id\"\n ></stream-attachment-list>\n <div\n data-testid=\"quoted-message-text\"\n [innerHTML]=\"quotedMessage?.html || quotedMessage?.text\"\n ></div>\n </div>\n </div>\n </div>\n <div class=\"str-chat__input-flat-wrapper\" style=\"width: 100%\">\n <div\n class=\"{{\n mode === 'main'\n ? 'str-chat__input-flat--textarea-wrapper'\n : 'str-chat__small-message-input--textarea-wrapper'\n }}\"\n >\n <ng-template\n #defaultAttachmentsPreview\n let-attachmentUploads$=\"attachmentUploads$\"\n let-retryUploadHandler=\"retryUploadHandler\"\n let-deleteUploadHandler=\"deleteUploadHandler\"\n >\n <stream-attachment-preview-list\n [attachmentUploads$]=\"attachmentUploads$\"\n (retryAttachmentUpload)=\"retryUploadHandler($event)\"\n (deleteAttachment)=\"deleteUploadHandler($event)\"\n class=\"rfu-image-previewer-angular-host\"\n ></stream-attachment-preview-list>\n </ng-template>\n <ng-container\n *ngTemplateOutlet=\"\n attachmentPreviewListTemplate || defaultAttachmentsPreview;\n context: getAttachmentPreviewListContext()\n \"\n ></ng-container>\n <div class=\"rta str-chat__textarea str-chat-angular__textarea\">\n <ng-container\n *ngIf=\"emojiPickerTemplate && !isCooldownInProgress\"\n data-testid=\"emoji-picker\"\n >\n <div\n class=\"\n str-chat__input-flat-emojiselect\n str-chat-angular__emojiselect\n \"\n >\n <ng-container\n *ngTemplateOutlet=\"\n emojiPickerTemplate;\n context: getEmojiPickerContext()\n \"\n ></ng-container>\n </div>\n </ng-container>\n <div\n class=\"str-chat__input-flat-cooldown str-chat-angular__cooldown\"\n *ngIf=\"isCooldownInProgress\"\n data-testid=\"cooldown-timer\"\n >\n {{ cooldown$ | async }}\n </div>\n <ng-template\n *ngIf=\"canSendMessages && !isCooldownInProgress; else notAllowed\"\n streamTextarea\n [(value)]=\"textareaValue\"\n (valueChange)=\"typingStart$.next()\"\n (send)=\"messageSent()\"\n [componentRef]=\"textareaRef\"\n (userMentions)=\"mentionedUsers = $event\"\n [areMentionsEnabled]=\"areMentionsEnabled\"\n [mentionScope]=\"mentionScope\"\n ></ng-template>\n <ng-template #notAllowed>\n <textarea\n disabled\n rows=\"1\"\n [value]=\"disabledTextareaText | translate\"\n class=\"rta__textarea str-chat__textarea__textarea\"\n data-testid=\"disabled-textarea\"\n ></textarea>\n </ng-template>\n </div>\n <div\n *ngIf=\"\n isFileUploadEnabled &&\n isFileUploadAuthorized &&\n canSendMessages &&\n !isCooldownInProgress\n \"\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 [multiple]=\"isMultipleFileUploadEnabled\"\n (change)=\"filesSelected(fileInput.files)\"\n />\n <span class=\"str-chat__input-flat-fileupload\">\n <stream-icon-placeholder\n icon=\"file-upload\"\n ></stream-icon-placeholder>\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-placeholder icon=\"send\"></stream-icon-placeholder>\n </button>\n </div>\n</div>\n", components: [{ type: IconPlaceholderComponent, selector: "stream-icon-placeholder", inputs: ["icon", "size"] }, { type: AvatarPlaceholderComponent, selector: "stream-avatar-placeholder", inputs: ["name", "imageUrl", "size"] }, { type: AttachmentListComponent, selector: "stream-attachment-list", inputs: ["messageId", "attachments"] }, { type: AttachmentPreviewListComponent, selector: "stream-attachment-preview-list", inputs: ["attachmentUploads$"], outputs: ["retryAttachmentUpload", "deleteAttachment"] }], directives: [{ type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i3.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet"] }, { type: TextareaDirective, selector: "[streamTextarea]", inputs: ["componentRef", "areMentionsEnabled", "mentionScope", "value"], outputs: ["valueChange", "send", "userMentions"] }], pipes: { "async": i3.AsyncPipe, "translate": i2.TranslatePipe } });
|
|
2341
2587
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: MessageInputComponent, decorators: [{
|
|
2342
2588
|
type: Component,
|
|
2343
2589
|
args: [{
|
|
@@ -2349,26 +2595,20 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImpor
|
|
|
2349
2595
|
}], ctorParameters: function () { return [{ type: ChannelService }, { type: NotificationService }, { type: AttachmentService }, { type: MessageInputConfigService }, { type: i0.Type, decorators: [{
|
|
2350
2596
|
type: Inject,
|
|
2351
2597
|
args: [textareaInjectionToken]
|
|
2352
|
-
}] }, { type: i0.ComponentFactoryResolver }, { type: i0.ChangeDetectorRef }, { type: ChatClientService }, { type: EmojiInputService }]; }, propDecorators: { isFileUploadEnabled: [{
|
|
2598
|
+
}] }, { type: i0.ComponentFactoryResolver }, { type: i0.ChangeDetectorRef }, { type: ChatClientService }, { type: EmojiInputService }, { type: CustomTemplatesService }]; }, propDecorators: { isFileUploadEnabled: [{
|
|
2353
2599
|
type: Input
|
|
2354
2600
|
}], areMentionsEnabled: [{
|
|
2355
2601
|
type: Input
|
|
2356
2602
|
}], mentionScope: [{
|
|
2357
2603
|
type: Input
|
|
2358
|
-
}], mentionAutocompleteItemTemplate: [{
|
|
2359
|
-
type: Input
|
|
2360
|
-
}], commandAutocompleteItemTemplate: [{
|
|
2361
|
-
type: Input
|
|
2362
|
-
}], emojiPickerTemplate: [{
|
|
2363
|
-
type: Input
|
|
2364
2604
|
}], mode: [{
|
|
2365
2605
|
type: Input
|
|
2366
|
-
}], acceptedFileTypes: [{
|
|
2367
|
-
type: Input
|
|
2368
2606
|
}], isMultipleFileUploadEnabled: [{
|
|
2369
2607
|
type: Input
|
|
2370
2608
|
}], message: [{
|
|
2371
2609
|
type: Input
|
|
2610
|
+
}], sendMessage$: [{
|
|
2611
|
+
type: Input
|
|
2372
2612
|
}], messageUpdate: [{
|
|
2373
2613
|
type: Output
|
|
2374
2614
|
}], fileInput: [{
|
|
@@ -2386,7 +2626,7 @@ class NotificationComponent {
|
|
|
2386
2626
|
constructor() { }
|
|
2387
2627
|
}
|
|
2388
2628
|
NotificationComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: NotificationComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2389
|
-
NotificationComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.5", type: NotificationComponent, selector: "stream-notification", inputs: { type: "type" }, ngImport: i0, template: "<div\n class=\"str-chat__custom-notification notification-{{ type }}\"\n data-testid=\"custom-notification\"\n>\n <ng-content></ng-content>\n</div>\n" });
|
|
2629
|
+
NotificationComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.5", type: NotificationComponent, selector: "stream-notification", inputs: { type: "type", content: "content" }, ngImport: i0, template: "<div\n class=\"str-chat__custom-notification notification-{{ type }}\"\n data-testid=\"custom-notification\"\n>\n <ng-container *ngIf=\"content; else elseContent\">\n <ng-container *ngTemplateOutlet=\"content\"></ng-container>\n </ng-container>\n <ng-template #elseContent>\n <ng-content></ng-content>\n </ng-template>\n</div>\n", directives: [{ type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i3.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet"] }] });
|
|
2390
2630
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: NotificationComponent, decorators: [{
|
|
2391
2631
|
type: Component,
|
|
2392
2632
|
args: [{
|
|
@@ -2396,25 +2636,28 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImpor
|
|
|
2396
2636
|
}]
|
|
2397
2637
|
}], ctorParameters: function () { return []; }, propDecorators: { type: [{
|
|
2398
2638
|
type: Input
|
|
2639
|
+
}], content: [{
|
|
2640
|
+
type: Input
|
|
2399
2641
|
}] } });
|
|
2400
2642
|
|
|
2401
2643
|
/**
|
|
2402
2644
|
* The `NotificationList` component displays the list of active notifications.
|
|
2403
2645
|
*/
|
|
2404
2646
|
class NotificationListComponent {
|
|
2405
|
-
constructor(notificationService) {
|
|
2647
|
+
constructor(customTemplatesService, notificationService) {
|
|
2648
|
+
this.customTemplatesService = customTemplatesService;
|
|
2406
2649
|
this.notificationService = notificationService;
|
|
2407
2650
|
this.notifications$ = this.notificationService.notifications$;
|
|
2408
2651
|
}
|
|
2409
2652
|
trackById(_, item) {
|
|
2410
2653
|
return item.id;
|
|
2411
2654
|
}
|
|
2412
|
-
|
|
2655
|
+
getNotificationContentContext(notification) {
|
|
2413
2656
|
return Object.assign(Object.assign({}, notification.templateContext), { dismissFn: notification.dismissFn });
|
|
2414
2657
|
}
|
|
2415
2658
|
}
|
|
2416
|
-
NotificationListComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: NotificationListComponent, deps: [{ token: NotificationService }], target: i0.ɵɵFactoryTarget.Component });
|
|
2417
|
-
NotificationListComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.5", type: NotificationListComponent, selector: "stream-notification-list", ngImport: i0, template: "<div class=\"str-chat__list-notifications\">\n <
|
|
2659
|
+
NotificationListComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: NotificationListComponent, deps: [{ token: CustomTemplatesService }, { token: NotificationService }], target: i0.ɵɵFactoryTarget.Component });
|
|
2660
|
+
NotificationListComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.5", type: NotificationListComponent, selector: "stream-notification-list", ngImport: i0, template: "<div class=\"str-chat__list-notifications\">\n <ng-container\n *ngFor=\"let notification of notifications$ | async; trackBy: trackById\"\n >\n <ng-template #notificationContent>\n <div\n *ngIf=\"notification.text !== undefined\"\n data-testclass=\"notification-content\"\n >\n {{ notification.text | translate: notification.translateParams }}\n </div>\n <ng-container *ngIf=\"notification.template !== undefined\">\n <ng-container\n *ngTemplateOutlet=\"\n notification.template;\n context: getNotificationContentContext(notification)\n \"\n ></ng-container>\n </ng-container>\n </ng-template>\n <ng-container\n *ngTemplateOutlet=\"\n (customTemplatesService.notificationTemplate$ | async) ||\n defaultNotification;\n context: { type: notification.type, content: notificationContent }\n \"\n ></ng-container>\n </ng-container>\n</div>\n\n<ng-template #defaultNotification let-type=\"type\" let-content=\"content\">\n <stream-notification [type]=\"type\" [content]=\"content\"></stream-notification>\n</ng-template>\n", components: [{ type: NotificationComponent, selector: "stream-notification", inputs: ["type", "content"] }], 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, "translate": i2.TranslatePipe } });
|
|
2418
2661
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: NotificationListComponent, decorators: [{
|
|
2419
2662
|
type: Component,
|
|
2420
2663
|
args: [{
|
|
@@ -2422,16 +2665,17 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImpor
|
|
|
2422
2665
|
templateUrl: './notification-list.component.html',
|
|
2423
2666
|
styles: [],
|
|
2424
2667
|
}]
|
|
2425
|
-
}], ctorParameters: function () { return [{ type: NotificationService }]; } });
|
|
2668
|
+
}], ctorParameters: function () { return [{ type: CustomTemplatesService }, { type: NotificationService }]; } });
|
|
2426
2669
|
|
|
2427
2670
|
/**
|
|
2428
2671
|
* 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.
|
|
2429
2672
|
*/
|
|
2430
2673
|
class MessageActionsBoxComponent {
|
|
2431
|
-
constructor(chatClientService, notificationService, channelService) {
|
|
2674
|
+
constructor(chatClientService, notificationService, channelService, customTemplatesService) {
|
|
2432
2675
|
this.chatClientService = chatClientService;
|
|
2433
2676
|
this.notificationService = notificationService;
|
|
2434
2677
|
this.channelService = channelService;
|
|
2678
|
+
this.customTemplatesService = customTemplatesService;
|
|
2435
2679
|
/**
|
|
2436
2680
|
* 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.
|
|
2437
2681
|
*/
|
|
@@ -2453,107 +2697,122 @@ class MessageActionsBoxComponent {
|
|
|
2453
2697
|
*/
|
|
2454
2698
|
this.isEditing = new EventEmitter();
|
|
2455
2699
|
this.isEditModalOpen = false;
|
|
2700
|
+
this.subscriptions = [];
|
|
2701
|
+
this.visibleMessageActionItems = [];
|
|
2702
|
+
this.sendMessageSubject = new Subject();
|
|
2456
2703
|
this.modalClosed = () => {
|
|
2457
2704
|
this.isEditModalOpen = false;
|
|
2458
2705
|
this.isEditing.emit(false);
|
|
2459
2706
|
};
|
|
2707
|
+
this.subscriptions.push(this.customTemplatesService.messageInputTemplate$.subscribe((template) => (this.messageInputTemplate = template)));
|
|
2708
|
+
this.subscriptions.push(this.customTemplatesService.messageActionsBoxItemTemplate$.subscribe((template) => (this.messageActionItemTemplate = template)));
|
|
2709
|
+
this.subscriptions.push(this.customTemplatesService.modalTemplate$.subscribe((template) => (this.modalTemplate = template)));
|
|
2710
|
+
this.messageActionItems = [
|
|
2711
|
+
{
|
|
2712
|
+
actionName: 'quote',
|
|
2713
|
+
actionLabelOrTranslationKey: 'streamChat.Reply',
|
|
2714
|
+
actionHandler: (message) => this.channelService.selectMessageToQuote(message),
|
|
2715
|
+
isVisible: (enabledActions, isMine, message) => enabledActions.indexOf('quote-message') !== -1 &&
|
|
2716
|
+
!(message === null || message === void 0 ? void 0 : message.quoted_message),
|
|
2717
|
+
},
|
|
2718
|
+
{
|
|
2719
|
+
actionName: 'pin',
|
|
2720
|
+
actionLabelOrTranslationKey: () => { var _a; return ((_a = this.message) === null || _a === void 0 ? void 0 : _a.pinned) ? 'streamChat.Unpin' : 'streamChat.Pin'; },
|
|
2721
|
+
actionHandler: () => alert('Feature not yet implemented'),
|
|
2722
|
+
isVisible: () => false,
|
|
2723
|
+
},
|
|
2724
|
+
{
|
|
2725
|
+
actionName: 'flag',
|
|
2726
|
+
actionLabelOrTranslationKey: 'streamChat.Flag',
|
|
2727
|
+
actionHandler: (message) => __awaiter(this, void 0, void 0, function* () {
|
|
2728
|
+
try {
|
|
2729
|
+
yield this.chatClientService.flagMessage(message.id);
|
|
2730
|
+
this.notificationService.addTemporaryNotification('streamChat.Message has been successfully flagged', 'success');
|
|
2731
|
+
}
|
|
2732
|
+
catch (err) {
|
|
2733
|
+
this.notificationService.addTemporaryNotification('streamChat.Error adding flag');
|
|
2734
|
+
}
|
|
2735
|
+
}),
|
|
2736
|
+
isVisible: (enabledActions, isMine) => enabledActions.indexOf('flag-message') !== -1 && !isMine,
|
|
2737
|
+
},
|
|
2738
|
+
{
|
|
2739
|
+
actionName: 'edit',
|
|
2740
|
+
actionLabelOrTranslationKey: 'streamChat.Edit Message',
|
|
2741
|
+
actionHandler: () => {
|
|
2742
|
+
this.isEditing.emit(true);
|
|
2743
|
+
this.isEditModalOpen = true;
|
|
2744
|
+
},
|
|
2745
|
+
isVisible: (enabledActions, isMine) => (enabledActions.indexOf('update-own-message') !== -1 && isMine) ||
|
|
2746
|
+
enabledActions.indexOf('update-any-message') !== -1,
|
|
2747
|
+
},
|
|
2748
|
+
{
|
|
2749
|
+
actionName: 'delete',
|
|
2750
|
+
actionLabelOrTranslationKey: 'streamChat.Delete',
|
|
2751
|
+
actionHandler: (message) => __awaiter(this, void 0, void 0, function* () {
|
|
2752
|
+
try {
|
|
2753
|
+
yield this.channelService.deleteMessage(message);
|
|
2754
|
+
}
|
|
2755
|
+
catch (error) {
|
|
2756
|
+
this.notificationService.addTemporaryNotification('streamChat.Error deleting message');
|
|
2757
|
+
}
|
|
2758
|
+
}),
|
|
2759
|
+
isVisible: (enabledActions, isMine) => ((enabledActions.indexOf('delete') !== -1 ||
|
|
2760
|
+
enabledActions.indexOf('delete-own-message') !== -1) &&
|
|
2761
|
+
isMine) ||
|
|
2762
|
+
enabledActions.indexOf('delete-any') !== -1 ||
|
|
2763
|
+
enabledActions.indexOf('delete-any-message') !== -1,
|
|
2764
|
+
},
|
|
2765
|
+
];
|
|
2766
|
+
this.sendMessage$ = this.sendMessageSubject.asObservable();
|
|
2460
2767
|
}
|
|
2461
2768
|
ngOnChanges(changes) {
|
|
2462
|
-
if (changes.isMine || changes.enabledActions) {
|
|
2463
|
-
|
|
2464
|
-
|
|
2465
|
-
|
|
2466
|
-
}
|
|
2467
|
-
if (this.isEditVisible) {
|
|
2468
|
-
displayedActionsCount++;
|
|
2469
|
-
}
|
|
2470
|
-
if (this.isDeleteVisible) {
|
|
2471
|
-
displayedActionsCount++;
|
|
2472
|
-
}
|
|
2473
|
-
if (this.isMuteVisible) {
|
|
2474
|
-
displayedActionsCount++;
|
|
2475
|
-
}
|
|
2476
|
-
if (this.isFlagVisible) {
|
|
2477
|
-
displayedActionsCount++;
|
|
2478
|
-
}
|
|
2479
|
-
if (this.isPinVisible) {
|
|
2480
|
-
displayedActionsCount++;
|
|
2481
|
-
}
|
|
2482
|
-
this.displayedActionsCount.next(displayedActionsCount);
|
|
2769
|
+
if (changes.isMine || changes.enabledActions || changes.message) {
|
|
2770
|
+
this.messageActionItems.forEach((i) => (i.actionHandler = i.actionHandler.bind(this, this.message, this.isMine)));
|
|
2771
|
+
this.visibleMessageActionItems = this.messageActionItems.filter((item) => item.isVisible(this.enabledActions, this.isMine, this.message));
|
|
2772
|
+
this.displayedActionsCount.emit(this.visibleMessageActionItems.length);
|
|
2483
2773
|
}
|
|
2484
2774
|
}
|
|
2485
|
-
|
|
2486
|
-
|
|
2487
|
-
return ((this.enabledActions.indexOf('quote') !== -1 ||
|
|
2488
|
-
this.enabledActions.indexOf('quote-message') !== -1) &&
|
|
2489
|
-
!((_a = this.message) === null || _a === void 0 ? void 0 : _a.quoted_message));
|
|
2490
|
-
}
|
|
2491
|
-
get isEditVisible() {
|
|
2492
|
-
return (((this.enabledActions.indexOf('edit') !== -1 ||
|
|
2493
|
-
this.enabledActions.indexOf('update-own-message') !== -1) &&
|
|
2494
|
-
this.isMine) ||
|
|
2495
|
-
this.enabledActions.indexOf('edit-any') !== -1 ||
|
|
2496
|
-
this.enabledActions.indexOf('update-any-message') !== -1);
|
|
2497
|
-
}
|
|
2498
|
-
get isDeleteVisible() {
|
|
2499
|
-
return (((this.enabledActions.indexOf('delete') !== -1 ||
|
|
2500
|
-
this.enabledActions.indexOf('delete-own-message') !== -1) &&
|
|
2501
|
-
this.isMine) ||
|
|
2502
|
-
this.enabledActions.indexOf('delete-any') !== -1 ||
|
|
2503
|
-
this.enabledActions.indexOf('delete-any-message') !== -1);
|
|
2504
|
-
}
|
|
2505
|
-
get isMuteVisible() {
|
|
2506
|
-
return this.enabledActions.indexOf('mute') !== -1;
|
|
2507
|
-
}
|
|
2508
|
-
get isFlagVisible() {
|
|
2509
|
-
return ((this.enabledActions.indexOf('flag') !== -1 ||
|
|
2510
|
-
this.enabledActions.indexOf('flag-message') !== -1) &&
|
|
2511
|
-
!this.isMine);
|
|
2512
|
-
}
|
|
2513
|
-
get isPinVisible() {
|
|
2514
|
-
return this.enabledActions.indexOf('pin') !== -1;
|
|
2515
|
-
}
|
|
2516
|
-
pinClicked() {
|
|
2517
|
-
alert('Feature not yet implemented');
|
|
2518
|
-
}
|
|
2519
|
-
flagClicked() {
|
|
2520
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
2521
|
-
try {
|
|
2522
|
-
yield this.chatClientService.flagMessage(this.message.id);
|
|
2523
|
-
this.notificationService.addTemporaryNotification('streamChat.Message has been successfully flagged', 'success');
|
|
2524
|
-
}
|
|
2525
|
-
catch (err) {
|
|
2526
|
-
this.notificationService.addTemporaryNotification('streamChat.Error adding flag');
|
|
2527
|
-
}
|
|
2528
|
-
});
|
|
2775
|
+
ngOnDestroy() {
|
|
2776
|
+
this.subscriptions.forEach((s) => s.unsubscribe());
|
|
2529
2777
|
}
|
|
2530
|
-
|
|
2531
|
-
|
|
2778
|
+
getActionLabel(actionLabelOrTranslationKey) {
|
|
2779
|
+
return typeof actionLabelOrTranslationKey === 'string'
|
|
2780
|
+
? actionLabelOrTranslationKey
|
|
2781
|
+
: actionLabelOrTranslationKey();
|
|
2532
2782
|
}
|
|
2533
|
-
|
|
2534
|
-
this.
|
|
2783
|
+
sendClicked() {
|
|
2784
|
+
this.sendMessageSubject.next();
|
|
2535
2785
|
}
|
|
2536
|
-
|
|
2537
|
-
|
|
2538
|
-
|
|
2786
|
+
getMessageInputContext() {
|
|
2787
|
+
return {
|
|
2788
|
+
message: this.message,
|
|
2789
|
+
messageUpdateHandler: this.modalClosed,
|
|
2790
|
+
isFileUploadEnabled: undefined,
|
|
2791
|
+
areMentionsEnabled: undefined,
|
|
2792
|
+
isMultipleFileUploadEnabled: undefined,
|
|
2793
|
+
mentionScope: undefined,
|
|
2794
|
+
mode: undefined,
|
|
2795
|
+
sendMessage$: this.sendMessage$,
|
|
2796
|
+
};
|
|
2539
2797
|
}
|
|
2540
|
-
|
|
2541
|
-
|
|
2542
|
-
|
|
2798
|
+
getEditModalContext() {
|
|
2799
|
+
return {
|
|
2800
|
+
isOpen: this.isEditModalOpen,
|
|
2801
|
+
isOpenChangeHandler: (isOpen) => {
|
|
2802
|
+
this.isEditModalOpen = isOpen;
|
|
2803
|
+
if (!this.isEditModalOpen) {
|
|
2804
|
+
this.modalClosed();
|
|
2805
|
+
}
|
|
2806
|
+
},
|
|
2807
|
+
content: this.modalContent,
|
|
2808
|
+
};
|
|
2543
2809
|
}
|
|
2544
|
-
|
|
2545
|
-
return
|
|
2546
|
-
try {
|
|
2547
|
-
yield this.channelService.deleteMessage(this.message);
|
|
2548
|
-
}
|
|
2549
|
-
catch (error) {
|
|
2550
|
-
this.notificationService.addTemporaryNotification('streamChat.Error deleting message');
|
|
2551
|
-
}
|
|
2552
|
-
});
|
|
2810
|
+
trackByActionName(_, item) {
|
|
2811
|
+
return item.actionName;
|
|
2553
2812
|
}
|
|
2554
2813
|
}
|
|
2555
|
-
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 });
|
|
2556
|
-
MessageActionsBoxComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.5", type: MessageActionsBoxComponent, selector: "stream-message-actions-box", inputs: {
|
|
2814
|
+
MessageActionsBoxComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: MessageActionsBoxComponent, deps: [{ token: ChatClientService }, { token: NotificationService }, { token: ChannelService }, { token: CustomTemplatesService }], target: i0.ɵɵFactoryTarget.Component });
|
|
2815
|
+
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: "modalContent", first: true, predicate: ["modalContent"], descendants: true, static: 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 <ng-container\n *ngFor=\"let item of visibleMessageActionItems; trackBy: trackByActionName\"\n >\n <ng-container\n *ngTemplateOutlet=\"\n messageActionItemTemplate || defaultMessageActionItem;\n context: 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 [attr.data-testid]=\"actionName + '-action'\" (click)=\"actionHandler()\">\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 modalTemplate || 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 (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 messageInputTemplate || 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 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</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$"], outputs: ["messageUpdate"] }, { type: NotificationListComponent, selector: "stream-notification-list" }], directives: [{ type: i3.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i3.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet"] }, { type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i2.TranslateDirective, selector: "[translate],[ngx-translate]", inputs: ["translate", "translateParams"] }], pipes: { "translate": i2.TranslatePipe } });
|
|
2557
2816
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: MessageActionsBoxComponent, decorators: [{
|
|
2558
2817
|
type: Component,
|
|
2559
2818
|
args: [{
|
|
@@ -2561,9 +2820,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImpor
|
|
|
2561
2820
|
templateUrl: './message-actions-box.component.html',
|
|
2562
2821
|
styles: [],
|
|
2563
2822
|
}]
|
|
2564
|
-
}], ctorParameters: function () { return [{ type: ChatClientService }, { type: NotificationService }, { type: ChannelService }]; }, propDecorators: {
|
|
2565
|
-
type: Input
|
|
2566
|
-
}], isOpen: [{
|
|
2823
|
+
}], ctorParameters: function () { return [{ type: ChatClientService }, { type: NotificationService }, { type: ChannelService }, { type: CustomTemplatesService }]; }, propDecorators: { isOpen: [{
|
|
2567
2824
|
type: Input
|
|
2568
2825
|
}], isMine: [{
|
|
2569
2826
|
type: Input
|
|
@@ -2575,9 +2832,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImpor
|
|
|
2575
2832
|
type: Output
|
|
2576
2833
|
}], isEditing: [{
|
|
2577
2834
|
type: Output
|
|
2578
|
-
}],
|
|
2835
|
+
}], modalContent: [{
|
|
2579
2836
|
type: ViewChild,
|
|
2580
|
-
args: [
|
|
2837
|
+
args: ['modalContent', { static: true }]
|
|
2581
2838
|
}] } });
|
|
2582
2839
|
|
|
2583
2840
|
/**
|
|
@@ -2593,7 +2850,7 @@ class ChannelComponent {
|
|
|
2593
2850
|
}
|
|
2594
2851
|
}
|
|
2595
2852
|
ChannelComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: ChannelComponent, deps: [{ token: ChannelService }], target: i0.ɵɵFactoryTarget.Component });
|
|
2596
|
-
ChannelComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.5", type: ChannelComponent, selector: "stream-channel", ngImport: i0, template: "<div\n *ngIf=\"(isError$ | async) === false && (isInitializing$ | async) === false\"\n class=\"str-chat str-chat-channel messaging\"\n>\n <div class=\"str-chat__container\">\n <div class=\"str-chat__main-panel\">\n <ng-content></ng-content>\n </div>\n <ng-content\n *ngIf=\"isActiveThread$ | async\"\n select='[name=\"thread\"]'\n ></ng-content>\n </div>\n</div>\n", directives: [{ type:
|
|
2853
|
+
ChannelComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.5", type: ChannelComponent, selector: "stream-channel", ngImport: i0, template: "<div\n *ngIf=\"(isError$ | async) === false && (isInitializing$ | async) === false\"\n class=\"str-chat str-chat-channel messaging\"\n>\n <div class=\"str-chat__container\">\n <div class=\"str-chat__main-panel\">\n <ng-content></ng-content>\n </div>\n <ng-content\n *ngIf=\"isActiveThread$ | async\"\n select='[name=\"thread\"]'\n ></ng-content>\n </div>\n</div>\n", directives: [{ type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }], pipes: { "async": i3.AsyncPipe } });
|
|
2597
2854
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: ChannelComponent, decorators: [{
|
|
2598
2855
|
type: Component,
|
|
2599
2856
|
args: [{
|
|
@@ -2687,9 +2944,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImpor
|
|
|
2687
2944
|
* The `ChannelHeader` component displays the avatar and name of the currently active channel along with member and watcher information. You can read about [the difference between members and watchers](https://getstream.io/chat/docs/javascript/watch_channel/?language=javascript#watchers-vs-members) in the platform documentation. Please note that number of watchers is only displayed if the user has [`connect-events` capability](https://getstream.io/chat/docs/javascript/channel_capabilities/?language=javascript)
|
|
2688
2945
|
*/
|
|
2689
2946
|
class ChannelHeaderComponent {
|
|
2690
|
-
constructor(channelService, channelListToggleService) {
|
|
2947
|
+
constructor(channelService, channelListToggleService, customTemplatesService, cdRef) {
|
|
2691
2948
|
this.channelService = channelService;
|
|
2692
2949
|
this.channelListToggleService = channelListToggleService;
|
|
2950
|
+
this.customTemplatesService = customTemplatesService;
|
|
2951
|
+
this.cdRef = cdRef;
|
|
2952
|
+
this.subscriptions = [];
|
|
2693
2953
|
this.channelService.activeChannel$.subscribe((c) => {
|
|
2694
2954
|
var _a, _b;
|
|
2695
2955
|
this.activeChannel = c;
|
|
@@ -2701,10 +2961,22 @@ class ChannelHeaderComponent {
|
|
|
2701
2961
|
capabilities.indexOf('connect-events') !== -1;
|
|
2702
2962
|
});
|
|
2703
2963
|
}
|
|
2964
|
+
ngOnInit() {
|
|
2965
|
+
this.subscriptions.push(this.customTemplatesService.channelActionsTemplate$.subscribe((template) => {
|
|
2966
|
+
this.channelActionsTemplate = template;
|
|
2967
|
+
this.cdRef.detectChanges();
|
|
2968
|
+
}));
|
|
2969
|
+
}
|
|
2970
|
+
ngOnDestroy() {
|
|
2971
|
+
this.subscriptions.forEach((s) => s.unsubscribe());
|
|
2972
|
+
}
|
|
2704
2973
|
toggleMenu(event) {
|
|
2705
2974
|
event.stopPropagation();
|
|
2706
2975
|
this.channelListToggleService.toggle();
|
|
2707
2976
|
}
|
|
2977
|
+
getChannelActionsContext() {
|
|
2978
|
+
return { channel: this.activeChannel };
|
|
2979
|
+
}
|
|
2708
2980
|
get memberCountParam() {
|
|
2709
2981
|
var _a, _b;
|
|
2710
2982
|
return { memberCount: ((_b = (_a = this.activeChannel) === null || _a === void 0 ? void 0 : _a.data) === null || _b === void 0 ? void 0 : _b.member_count) || 0 };
|
|
@@ -2714,8 +2986,8 @@ class ChannelHeaderComponent {
|
|
|
2714
2986
|
return { watcherCount: ((_b = (_a = this.activeChannel) === null || _a === void 0 ? void 0 : _a.state) === null || _b === void 0 ? void 0 : _b.watcher_count) || 0 };
|
|
2715
2987
|
}
|
|
2716
2988
|
}
|
|
2717
|
-
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 });
|
|
2718
|
-
ChannelHeaderComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.5", type: ChannelHeaderComponent, selector: "stream-channel-header",
|
|
2989
|
+
ChannelHeaderComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: ChannelHeaderComponent, deps: [{ token: ChannelService }, { token: ChannelListToggleService }, { token: CustomTemplatesService }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
|
|
2990
|
+
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 <stream-icon-placeholder icon=\"menu\"></stream-icon-placeholder>\n </div>\n <stream-avatar-placeholder\n imageUrl=\"{{ activeChannel?.data?.image }}\"\n name=\"{{ activeChannel?.data?.name }}\"\n ></stream-avatar-placeholder>\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 <ng-container *ngIf=\"channelActionsTemplate\">\n <ng-container\n *ngTemplateOutlet=\"\n channelActionsTemplate;\n context: getChannelActionsContext()\n \"\n ></ng-container>\n </ng-container>\n</div>\n", components: [{ type: IconPlaceholderComponent, selector: "stream-icon-placeholder", inputs: ["icon", "size"] }, { type: AvatarPlaceholderComponent, selector: "stream-avatar-placeholder", inputs: ["name", "imageUrl", "size"] }], directives: [{ type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i3.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet"] }], pipes: { "translate": i2.TranslatePipe } });
|
|
2719
2991
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: ChannelHeaderComponent, decorators: [{
|
|
2720
2992
|
type: Component,
|
|
2721
2993
|
args: [{
|
|
@@ -2723,9 +2995,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImpor
|
|
|
2723
2995
|
templateUrl: './channel-header.component.html',
|
|
2724
2996
|
styles: [],
|
|
2725
2997
|
}]
|
|
2726
|
-
}], ctorParameters: function () { return [{ type: ChannelService }, { type: ChannelListToggleService }
|
|
2727
|
-
type: Input
|
|
2728
|
-
}] } });
|
|
2998
|
+
}], ctorParameters: function () { return [{ type: ChannelService }, { type: ChannelListToggleService }, { type: CustomTemplatesService }, { type: i0.ChangeDetectorRef }]; } });
|
|
2729
2999
|
|
|
2730
3000
|
/**
|
|
2731
3001
|
* The `ChannelPreview` component displays a channel preview in the channel list, it consists of the image, name and latest message of the channel.
|
|
@@ -2805,7 +3075,7 @@ class ChannelPreviewComponent {
|
|
|
2805
3075
|
}
|
|
2806
3076
|
}
|
|
2807
3077
|
ChannelPreviewComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: ChannelPreviewComponent, deps: [{ token: ChannelService }, { token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Component });
|
|
2808
|
-
ChannelPreviewComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.5", type: ChannelPreviewComponent, selector: "stream-channel-preview", inputs: { channel: "channel" }, ngImport: i0, template: "<button\n class=\"str-chat__channel-preview-messenger\"\n [class.str-chat__channel-preview-messenger--active]=\"isActive\"\n [class.str-chat__channel-preview-messenger--unread]=\"isUnread\"\n (click)=\"setAsActiveChannel()\"\n data-testid=\"channel-preview-container\"\n>\n <div class=\"str-chat__channel-preview-messenger--left\">\n <stream-avatar\n imageUrl=\"{{ avatarImage }}\"\n name=\"{{ avatarName }}\"\n [size]=\"40\"\n ></stream-avatar>\n </div>\n <div class=\"str-chat__channel-preview-messenger--right\">\n <div class=\"str-chat__channel-preview-messenger--name\">\n <span data-testid=\"channel-preview-title\">{{ title }}</span>\n </div>\n <div\n data-testid=\"latest-message\"\n class=\"str-chat__channel-preview-messenger--last-message\"\n >\n {{ latestMessage | translate }}\n </div>\n </div>\n</button>\n", components: [{ type:
|
|
3078
|
+
ChannelPreviewComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.5", type: ChannelPreviewComponent, selector: "stream-channel-preview", inputs: { channel: "channel" }, ngImport: i0, template: "<button\n class=\"str-chat__channel-preview-messenger\"\n [class.str-chat__channel-preview-messenger--active]=\"isActive\"\n [class.str-chat__channel-preview-messenger--unread]=\"isUnread\"\n (click)=\"setAsActiveChannel()\"\n data-testid=\"channel-preview-container\"\n>\n <div class=\"str-chat__channel-preview-messenger--left\">\n <stream-avatar-placeholder\n imageUrl=\"{{ avatarImage }}\"\n name=\"{{ avatarName }}\"\n [size]=\"40\"\n ></stream-avatar-placeholder>\n </div>\n <div class=\"str-chat__channel-preview-messenger--right\">\n <div class=\"str-chat__channel-preview-messenger--name\">\n <span data-testid=\"channel-preview-title\">{{ title }}</span>\n </div>\n <div\n data-testid=\"latest-message\"\n class=\"str-chat__channel-preview-messenger--last-message\"\n >\n {{ latestMessage | translate }}\n </div>\n </div>\n</button>\n", components: [{ type: AvatarPlaceholderComponent, selector: "stream-avatar-placeholder", inputs: ["name", "imageUrl", "size"] }], pipes: { "translate": i2.TranslatePipe } });
|
|
2809
3079
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: ChannelPreviewComponent, decorators: [{
|
|
2810
3080
|
type: Component,
|
|
2811
3081
|
args: [{
|
|
@@ -2821,19 +3091,25 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImpor
|
|
|
2821
3091
|
* The `ChannelList` component renders the list of channels.
|
|
2822
3092
|
*/
|
|
2823
3093
|
class ChannelListComponent {
|
|
2824
|
-
constructor(channelService, channelListToggleService) {
|
|
3094
|
+
constructor(channelService, channelListToggleService, customTemplatesService) {
|
|
2825
3095
|
this.channelService = channelService;
|
|
2826
3096
|
this.channelListToggleService = channelListToggleService;
|
|
3097
|
+
this.customTemplatesService = customTemplatesService;
|
|
2827
3098
|
this.isLoadingMoreChannels = false;
|
|
3099
|
+
this.subscriptions = [];
|
|
2828
3100
|
this.isOpen$ = this.channelListToggleService.isOpen$;
|
|
2829
3101
|
this.channels$ = this.channelService.channels$;
|
|
2830
3102
|
this.hasMoreChannels$ = this.channelService.hasMoreChannels$;
|
|
2831
3103
|
this.isError$ = this.channels$.pipe(map(() => false), catchError(() => of(true)), startWith(false));
|
|
2832
3104
|
this.isInitializing$ = this.channels$.pipe(map((channels) => !channels), catchError(() => of(false)));
|
|
3105
|
+
this.subscriptions.push(this.customTemplatesService.channelPreviewTemplate$.subscribe((template) => (this.customChannelPreviewTemplate = template)));
|
|
2833
3106
|
}
|
|
2834
3107
|
ngAfterViewInit() {
|
|
2835
3108
|
this.channelListToggleService.setMenuElement(this.container.nativeElement);
|
|
2836
3109
|
}
|
|
3110
|
+
ngOnDestroy() {
|
|
3111
|
+
this.subscriptions.forEach((s) => s.unsubscribe());
|
|
3112
|
+
}
|
|
2837
3113
|
loadMoreChannels() {
|
|
2838
3114
|
return __awaiter(this, void 0, void 0, function* () {
|
|
2839
3115
|
this.isLoadingMoreChannels = true;
|
|
@@ -2847,9 +3123,14 @@ class ChannelListComponent {
|
|
|
2847
3123
|
channelSelected() {
|
|
2848
3124
|
this.channelListToggleService.channelSelected();
|
|
2849
3125
|
}
|
|
3126
|
+
getChannelPreviewContext(channel) {
|
|
3127
|
+
return {
|
|
3128
|
+
channel,
|
|
3129
|
+
};
|
|
3130
|
+
}
|
|
2850
3131
|
}
|
|
2851
|
-
ChannelListComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: ChannelListComponent, deps: [{ token: ChannelService }, { token: ChannelListToggleService }], target: i0.ɵɵFactoryTarget.Component });
|
|
2852
|
-
ChannelListComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.5", type: ChannelListComponent, selector: "stream-channel-list",
|
|
3132
|
+
ChannelListComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: ChannelListComponent, deps: [{ token: ChannelService }, { token: ChannelListToggleService }, { token: CustomTemplatesService }], target: i0.ɵɵFactoryTarget.Component });
|
|
3133
|
+
ChannelListComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.5", type: ChannelListComponent, selector: "stream-channel-list", viewQueries: [{ propertyName: "container", first: true, predicate: ["container"], descendants: true }], ngImport: i0, template: "<div\n #container\n data-testid=\"channel-list-container\"\n class=\"str-chat str-chat-channel-list messaging\"\n [class.str-chat-channel-list--open]=\"(isOpen$ | async) === true\"\n>\n <div\n *ngIf=\"\n (isError$ | async) === false && (isInitializing$ | async) === false;\n else statusIndicator\n \"\n class=\"str-chat__channel-list-messenger\"\n >\n <div class=\"str-chat__channel-list-messenger__main\">\n <p\n data-testid=\"empty-channel-list-indicator\"\n *ngIf=\"!(channels$ | async)?.length\"\n >\n {{ \"streamChat.You have no channels currently\" | translate }}\n </p>\n <ng-container\n *ngFor=\"let channel of channels$ | async; trackBy: trackByChannelId\"\n >\n <ng-template #defaultTemplate let-channelInput=\"channel\">\n <stream-channel-preview\n data-testclass=\"channel-preview\"\n [channel]=\"channelInput\"\n ></stream-channel-preview>\n </ng-template>\n <div (click)=\"channelSelected()\" (keyup.enter)=\"channelSelected()\">\n <ng-container\n *ngTemplateOutlet=\"\n customChannelPreviewTemplate || defaultTemplate;\n context: getChannelPreviewContext(channel)\n \"\n ></ng-container>\n </div>\n </ng-container>\n <div\n *ngIf=\"hasMoreChannels$ | async\"\n class=\"str-chat__load-more-button\"\n (click)=\"loadMoreChannels()\"\n (keyup.enter)=\"loadMoreChannels()\"\n data-testid=\"load-more\"\n >\n <button\n class=\"str-chat__load-more-button__button\"\n data-testid=\"load-more-button\"\n [disabled]=\"isLoadingMoreChannels\"\n >\n <span *ngIf=\"!isLoadingMoreChannels; else loadingIndicator\">{{\n \"Load more\" | translate\n }}</span>\n <ng-template #loadingIndicator\n ><stream-loading-indicator-placeholder></stream-loading-indicator-placeholder\n ></ng-template>\n </button>\n </div>\n </div>\n </div>\n</div>\n\n<ng-template #statusIndicator>\n <ng-container *ngIf=\"isError$ | async\">\n <ng-container *ngTemplateOutlet=\"chatDown\"></ng-container>\n </ng-container>\n <ng-container *ngIf=\"isInitializing$ | async\">\n <ng-container *ngTemplateOutlet=\"loadingChannels\"></ng-container>\n </ng-container>\n</ng-template>\n\n<ng-template #chatDown>\n <div data-testid=\"chatdown-container\" class=\"str-chat__down\">\n <ng-container *ngTemplateOutlet=\"loadingChannels\"></ng-container>\n <div class=\"str-chat__down-main\">\n <stream-icon-placeholder\n icon=\"connection-error\"\n ></stream-icon-placeholder>\n <h1>{{ \"streamChat.Connection error\" | translate }}</h1>\n <h3>\n {{\n \"streamChat.Error connecting to chat, refresh the page to try again.\"\n | translate\n }}\n </h3>\n </div>\n </div>\n</ng-template>\n\n<ng-template #loadingChannels>\n <div data-testid=\"loading-indicator\" class=\"str-chat__loading-channels\">\n <ng-container *ngTemplateOutlet=\"loadingChannel\"></ng-container>\n <ng-container *ngTemplateOutlet=\"loadingChannel\"></ng-container>\n <ng-container *ngTemplateOutlet=\"loadingChannel\"></ng-container>\n </div>\n</ng-template>\n\n<ng-template #loadingChannel>\n <div class=\"str-chat__loading-channels-item\">\n <div class=\"str-chat__loading-channels-avatar\"></div>\n <div class=\"str-chat__loading-channels-meta\">\n <div class=\"str-chat__loading-channels-username\"></div>\n <div class=\"str-chat__loading-channels-status\"></div>\n </div>\n </div>\n</ng-template>\n", components: [{ type: ChannelPreviewComponent, selector: "stream-channel-preview", inputs: ["channel"] }, { type: LoadingIndicatorPlaceholderComponent, selector: "stream-loading-indicator-placeholder", inputs: ["size", "color"] }, { type: IconPlaceholderComponent, selector: "stream-icon-placeholder", inputs: ["icon", "size"] }], directives: [{ type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i3.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i3.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet"] }], pipes: { "async": i3.AsyncPipe, "translate": i2.TranslatePipe } });
|
|
2853
3134
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: ChannelListComponent, decorators: [{
|
|
2854
3135
|
type: Component,
|
|
2855
3136
|
args: [{
|
|
@@ -2857,9 +3138,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImpor
|
|
|
2857
3138
|
templateUrl: './channel-list.component.html',
|
|
2858
3139
|
styles: [],
|
|
2859
3140
|
}]
|
|
2860
|
-
}], ctorParameters: function () { return [{ type: ChannelService }, { type: ChannelListToggleService }]; }, propDecorators: {
|
|
2861
|
-
type: Input
|
|
2862
|
-
}], container: [{
|
|
3141
|
+
}], ctorParameters: function () { return [{ type: ChannelService }, { type: ChannelListToggleService }, { type: CustomTemplatesService }]; }, propDecorators: { container: [{
|
|
2863
3142
|
type: ViewChild,
|
|
2864
3143
|
args: ['container']
|
|
2865
3144
|
}] } });
|
|
@@ -3018,7 +3297,7 @@ class MessageReactionsComponent {
|
|
|
3018
3297
|
}
|
|
3019
3298
|
}
|
|
3020
3299
|
MessageReactionsComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: MessageReactionsComponent, deps: [{ token: i0.ChangeDetectorRef }, { token: ChannelService }], target: i0.ɵɵFactoryTarget.Component });
|
|
3021
|
-
MessageReactionsComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.5", type: MessageReactionsComponent, selector: "stream-message-reactions", inputs: { messageId: "messageId", messageReactionCounts: "messageReactionCounts", isSelectorOpen: "isSelectorOpen", latestReactions: "latestReactions", ownReactions: "ownReactions" }, outputs: { isSelectorOpenChange: "isSelectorOpenChange" }, viewQueries: [{ propertyName: "selectorContainer", first: true, predicate: ["selectorContainer"], descendants: true }, { propertyName: "selectorTooltip", first: true, predicate: ["selectorTooltip"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div\n *ngIf=\"existingReactions.length > 0 && !isSelectorOpen\"\n class=\"str-chat__reaction-list\"\n [class.str-chat__reaction-list--reverse]=\"true\"\n data-testid=\"reaction-list\"\n>\n <ul>\n <li\n *ngFor=\"\n let reactionType of existingReactions;\n trackBy: trackByMessageReaction\n \"\n data-testclass=\"emoji\"\n >\n <span class=\"emoji\">\n {{ getEmojiByReaction(reactionType) }}\n </span>\n \n </li>\n <li>\n <span\n data-testid=\"reactions-count\"\n class=\"str-chat__reaction-list--counter\"\n >{{ reactionsCount }}</span\n >\n </li>\n </ul>\n</div>\n\n<div\n #selectorContainer\n class=\"str-chat__reaction-selector\"\n *ngIf=\"isSelectorOpen\"\n data-testid=\"reaction-selector\"\n>\n <div\n *ngIf=\"tooltipText\"\n data-testid=\"tooltip\"\n #selectorTooltip\n class=\"str-chat__reaction-selector-tooltip\"\n [ngStyle]=\"{\n left: tooltipPositions?.tooltip + 'px',\n visibility: tooltipPositions ? 'visible' : 'hidden'\n }\"\n >\n <div\n class=\"arrow\"\n [ngStyle]=\"{ left: tooltipPositions?.arrow + 'px' }\"\n ></div>\n <span class=\"latest-user-username\">\n {{ tooltipText }}\n </span>\n </div>\n <ul class=\"str-chat__message-reactions-list\">\n <li\n class=\"str-chat__message-reactions-list-item str-chat__emoji\"\n *ngFor=\"\n let reactionType of reactionOptions;\n trackBy: trackByMessageReaction\n \"\n data-testclass=\"emoji-option\"\n (click)=\"react(reactionType)\"\n (keyup.enter)=\"react(reactionType)\"\n >\n <div\n *ngIf=\"getLatestUserByReaction(reactionType) as user\"\n class=\"latest-user\"\n (click)=\"hideTooltip()\"\n (keyup.enter)=\"hideTooltip()\"\n (mouseenter)=\"showTooltip($event, reactionType)\"\n (mouseleave)=\"hideTooltip()\"\n attr.data-testid=\"{{ reactionType }}-last-user\"\n >\n <stream-avatar\n attr.data-testid=\"{{ reactionType }}-avatar\"\n [imageUrl]=\"user.image\"\n [name]=\"user.name || user.id\"\n [size]=\"20\"\n ></stream-avatar>\n </div>\n <span class=\"emoji\" style=\"width: 20px; height: 20px; top: 10px\">\n {{ getEmojiByReaction(reactionType) }}\n </span>\n <span\n *ngIf=\"\n messageReactionCounts[reactionType] &&\n messageReactionCounts[reactionType]! > 0\n \"\n class=\"str-chat__message-reactions-list-item__count\"\n attr.data-testid=\"{{ reactionType }}-reaction-count\"\n >\n {{ messageReactionCounts[reactionType] }}\n </span>\n </li>\n </ul>\n</div>\n", styles: [".emoji {position: relative; display: inline-block; }"], components: [{ type:
|
|
3300
|
+
MessageReactionsComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.5", type: MessageReactionsComponent, selector: "stream-message-reactions", inputs: { messageId: "messageId", messageReactionCounts: "messageReactionCounts", isSelectorOpen: "isSelectorOpen", latestReactions: "latestReactions", ownReactions: "ownReactions" }, outputs: { isSelectorOpenChange: "isSelectorOpenChange" }, viewQueries: [{ propertyName: "selectorContainer", first: true, predicate: ["selectorContainer"], descendants: true }, { propertyName: "selectorTooltip", first: true, predicate: ["selectorTooltip"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div\n *ngIf=\"existingReactions.length > 0 && !isSelectorOpen\"\n class=\"str-chat__reaction-list\"\n [class.str-chat__reaction-list--reverse]=\"true\"\n data-testid=\"reaction-list\"\n>\n <ul>\n <li\n *ngFor=\"\n let reactionType of existingReactions;\n trackBy: trackByMessageReaction\n \"\n data-testclass=\"emoji\"\n >\n <span class=\"emoji\">\n {{ getEmojiByReaction(reactionType) }}\n </span>\n \n </li>\n <li>\n <span\n data-testid=\"reactions-count\"\n class=\"str-chat__reaction-list--counter\"\n >{{ reactionsCount }}</span\n >\n </li>\n </ul>\n</div>\n\n<div\n #selectorContainer\n class=\"str-chat__reaction-selector\"\n *ngIf=\"isSelectorOpen\"\n data-testid=\"reaction-selector\"\n>\n <div\n *ngIf=\"tooltipText\"\n data-testid=\"tooltip\"\n #selectorTooltip\n class=\"str-chat__reaction-selector-tooltip\"\n [ngStyle]=\"{\n left: tooltipPositions?.tooltip + 'px',\n visibility: tooltipPositions ? 'visible' : 'hidden'\n }\"\n >\n <div\n class=\"arrow\"\n [ngStyle]=\"{ left: tooltipPositions?.arrow + 'px' }\"\n ></div>\n <span class=\"latest-user-username\">\n {{ tooltipText }}\n </span>\n </div>\n <ul class=\"str-chat__message-reactions-list\">\n <li\n class=\"str-chat__message-reactions-list-item str-chat__emoji\"\n *ngFor=\"\n let reactionType of reactionOptions;\n trackBy: trackByMessageReaction\n \"\n data-testclass=\"emoji-option\"\n (click)=\"react(reactionType)\"\n (keyup.enter)=\"react(reactionType)\"\n >\n <div\n *ngIf=\"getLatestUserByReaction(reactionType) as user\"\n class=\"latest-user\"\n (click)=\"hideTooltip()\"\n (keyup.enter)=\"hideTooltip()\"\n (mouseenter)=\"showTooltip($event, reactionType)\"\n (mouseleave)=\"hideTooltip()\"\n attr.data-testid=\"{{ reactionType }}-last-user\"\n >\n <stream-avatar-placeholder\n attr.data-testid=\"{{ reactionType }}-avatar\"\n [imageUrl]=\"user.image\"\n [name]=\"user.name || user.id\"\n [size]=\"20\"\n ></stream-avatar-placeholder>\n </div>\n <span class=\"emoji\" style=\"width: 20px; height: 20px; top: 10px\">\n {{ getEmojiByReaction(reactionType) }}\n </span>\n <span\n *ngIf=\"\n messageReactionCounts[reactionType] &&\n messageReactionCounts[reactionType]! > 0\n \"\n class=\"str-chat__message-reactions-list-item__count\"\n attr.data-testid=\"{{ reactionType }}-reaction-count\"\n >\n {{ messageReactionCounts[reactionType] }}\n </span>\n </li>\n </ul>\n</div>\n", styles: [".emoji {position: relative; display: inline-block; }"], components: [{ type: AvatarPlaceholderComponent, selector: "stream-avatar-placeholder", inputs: ["name", "imageUrl", "size"] }], directives: [{ type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i3.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i3.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }] });
|
|
3022
3301
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: MessageReactionsComponent, decorators: [{
|
|
3023
3302
|
type: Component,
|
|
3024
3303
|
args: [{
|
|
@@ -3050,9 +3329,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImpor
|
|
|
3050
3329
|
* The `Message` component displays a message with additional information such as sender and date, and enables [interaction with the message (i.e. edit or react)](../concepts/message-interactions.mdx).
|
|
3051
3330
|
*/
|
|
3052
3331
|
class MessageComponent {
|
|
3053
|
-
constructor(chatClientService, channelService) {
|
|
3332
|
+
constructor(chatClientService, channelService, customTemplatesService, cdRef) {
|
|
3054
3333
|
this.chatClientService = chatClientService;
|
|
3055
3334
|
this.channelService = channelService;
|
|
3335
|
+
this.customTemplatesService = customTemplatesService;
|
|
3336
|
+
this.cdRef = cdRef;
|
|
3056
3337
|
/**
|
|
3057
3338
|
* 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. The [`MessageList`](./MessageListComponent.mdx) component automatically sets this based on [channel capabilities](https://getstream.io/chat/docs/javascript/channel_capabilities/?language=javascript).
|
|
3058
3339
|
*/
|
|
@@ -3066,12 +3347,28 @@ class MessageComponent {
|
|
|
3066
3347
|
this.isPressedOnMobile = false;
|
|
3067
3348
|
this.visibleMessageActionsCount = 0;
|
|
3068
3349
|
this.messageTextParts = [];
|
|
3350
|
+
this.subscriptions = [];
|
|
3069
3351
|
this.user = this.chatClientService.chatClient.user;
|
|
3070
3352
|
}
|
|
3353
|
+
ngOnInit() {
|
|
3354
|
+
this.subscriptions.push(this.customTemplatesService.mentionTemplate$.subscribe((template) => (this.mentionTemplate = template)));
|
|
3355
|
+
this.subscriptions.push(this.customTemplatesService.attachmentListTemplate$.subscribe((template) => (this.attachmentListTemplate = template)));
|
|
3356
|
+
this.subscriptions.push(this.customTemplatesService.messageActionsBoxTemplate$.subscribe((template) => (this.messageActionsBoxTemplate = template)));
|
|
3357
|
+
this.subscriptions.push(this.customTemplatesService.messageReactionsTemplate$.subscribe((template) => (this.messageReactionsTemplate = template)));
|
|
3358
|
+
}
|
|
3071
3359
|
ngOnChanges(changes) {
|
|
3072
3360
|
if (changes.message) {
|
|
3073
3361
|
this.createMessageParts();
|
|
3074
3362
|
}
|
|
3363
|
+
if (changes.enabledMessageActions) {
|
|
3364
|
+
this.canReactToMessage =
|
|
3365
|
+
this.enabledMessageActions.indexOf('send-reaction') !== -1;
|
|
3366
|
+
this.canReceiveReadEvents =
|
|
3367
|
+
this.enabledMessageActions.indexOf('read-events') !== -1;
|
|
3368
|
+
}
|
|
3369
|
+
}
|
|
3370
|
+
ngOnDestroy() {
|
|
3371
|
+
this.subscriptions.forEach((s) => s.unsubscribe());
|
|
3075
3372
|
}
|
|
3076
3373
|
get isSentByCurrentUser() {
|
|
3077
3374
|
var _a, _b, _c;
|
|
@@ -3139,6 +3436,24 @@ class MessageComponent {
|
|
|
3139
3436
|
? [originalAttachments[0]]
|
|
3140
3437
|
: [];
|
|
3141
3438
|
}
|
|
3439
|
+
getAttachmentListContext() {
|
|
3440
|
+
var _a, _b;
|
|
3441
|
+
return {
|
|
3442
|
+
messageId: ((_a = this.message) === null || _a === void 0 ? void 0 : _a.id) || '',
|
|
3443
|
+
attachments: ((_b = this.message) === null || _b === void 0 ? void 0 : _b.attachments) || [],
|
|
3444
|
+
};
|
|
3445
|
+
}
|
|
3446
|
+
getMessageReactionsContext() {
|
|
3447
|
+
var _a, _b, _c, _d;
|
|
3448
|
+
return {
|
|
3449
|
+
messageReactionCounts: ((_a = this.message) === null || _a === void 0 ? void 0 : _a.reaction_counts) || {},
|
|
3450
|
+
latestReactions: ((_b = this.message) === null || _b === void 0 ? void 0 : _b.latest_reactions) || [],
|
|
3451
|
+
isSelectorOpen: this.isReactionSelectorOpen,
|
|
3452
|
+
isSelectorOpenChangeHandler: (isOpen) => (this.isReactionSelectorOpen = isOpen),
|
|
3453
|
+
messageId: (_c = this.message) === null || _c === void 0 ? void 0 : _c.id,
|
|
3454
|
+
ownReactions: ((_d = this.message) === null || _d === void 0 ? void 0 : _d.own_reactions) || [],
|
|
3455
|
+
};
|
|
3456
|
+
}
|
|
3142
3457
|
resendMessage() {
|
|
3143
3458
|
void this.channelService.resendMessage(this.message);
|
|
3144
3459
|
}
|
|
@@ -3163,6 +3478,29 @@ class MessageComponent {
|
|
|
3163
3478
|
setAsActiveParentMessage() {
|
|
3164
3479
|
void this.channelService.setAsActiveParentMessage(this.message);
|
|
3165
3480
|
}
|
|
3481
|
+
getMentionContext(messagePart) {
|
|
3482
|
+
return {
|
|
3483
|
+
content: messagePart.content,
|
|
3484
|
+
user: messagePart.user,
|
|
3485
|
+
};
|
|
3486
|
+
}
|
|
3487
|
+
getMessageActionsBoxContext() {
|
|
3488
|
+
return {
|
|
3489
|
+
isOpen: this.isActionBoxOpen,
|
|
3490
|
+
isMine: this.isSentByCurrentUser,
|
|
3491
|
+
enabledActions: this.enabledMessageActions,
|
|
3492
|
+
message: this.message,
|
|
3493
|
+
displayedActionsCountChaneHanler: (count) => {
|
|
3494
|
+
this.visibleMessageActionsCount = count;
|
|
3495
|
+
// message action box changes UI bindings in parent, so we'll have to rerun change detection
|
|
3496
|
+
this.cdRef.detectChanges();
|
|
3497
|
+
},
|
|
3498
|
+
isEditingChangeHandler: (isEditing) => {
|
|
3499
|
+
this.isEditing = isEditing;
|
|
3500
|
+
this.isActionBoxOpen = !this.isEditing;
|
|
3501
|
+
},
|
|
3502
|
+
};
|
|
3503
|
+
}
|
|
3166
3504
|
createMessageParts() {
|
|
3167
3505
|
var _a, _b;
|
|
3168
3506
|
let content = ((_a = this.message) === null || _a === void 0 ? void 0 : _a.html) || ((_b = this.message) === null || _b === void 0 ? void 0 : _b.text);
|
|
@@ -3181,12 +3519,7 @@ class MessageComponent {
|
|
|
3181
3519
|
this.message.mentioned_users.length === 0) {
|
|
3182
3520
|
// Wrap emojis in span to display emojis correctly in Chrome https://bugs.chromium.org/p/chromium/issues/detail?id=596223
|
|
3183
3521
|
const regex = new RegExp(emojiRegex(), 'g');
|
|
3184
|
-
|
|
3185
|
-
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
|
3186
|
-
const isChrome = !!window.chrome &&
|
|
3187
|
-
typeof window.opr === 'undefined';
|
|
3188
|
-
/* eslint-enable @typescript-eslint/no-unsafe-member-access */
|
|
3189
|
-
content = content.replace(regex, (match) => `<span ${isChrome ? 'class="str-chat__emoji-display-fix"' : ''}>${match}</span>`);
|
|
3522
|
+
content = content.replace(regex, (match) => `<span class="str-chat__emoji-display-fix">${match}</span>`);
|
|
3190
3523
|
this.messageTextParts = [{ content, type: 'text' }];
|
|
3191
3524
|
}
|
|
3192
3525
|
else {
|
|
@@ -3213,8 +3546,8 @@ class MessageComponent {
|
|
|
3213
3546
|
}
|
|
3214
3547
|
}
|
|
3215
3548
|
}
|
|
3216
|
-
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 });
|
|
3217
|
-
MessageComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.5", type: MessageComponent, selector: "stream-message", inputs: { messageInputTemplate: "messageInputTemplate", mentionTemplate: "mentionTemplate", message: "message", enabledMessageActions: "enabledMessageActions", areReactionsEnabled: "areReactionsEnabled", canReactToMessage: "canReactToMessage", isLastSentMessage: "isLastSentMessage", canReceiveReadEvents: "canReceiveReadEvents", mode: "mode" }, viewQueries: [{ propertyName: "container", first: true, predicate: ["container"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div\n #container\n class=\"str-chat__message-simple str-chat__message str-chat__message--{{\n message?.type\n }} str-chat__message--{{ message?.status }} {{\n message?.text ? 'str-chat__message--has-text' : 'has-no-text'\n }}\"\n [class.str-chat__message--me]=\"isSentByCurrentUser\"\n [class.str-chat__message-simple--me]=\"isSentByCurrentUser\"\n [class.mobile-press]=\"isPressedOnMobile\"\n [class.str-chat__message--has-attachment]=\"hasAttachment\"\n [class.str-chat__message--with-reactions]=\"\n areReactionsEnabled !== false && hasReactions\n \"\n data-testid=\"message-container\"\n (mouseleave)=\"isActionBoxOpen = false\"\n>\n <ng-container *ngIf=\"!message?.deleted_at; else deletedMessage\">\n <ng-container *ngIf=\"message?.type !== 'system'; else systemMessage\">\n <ng-container\n *ngIf=\"\n isSentByCurrentUser &&\n ((isLastSentMessage && message?.status === 'received') ||\n message?.status === 'sending')\n \"\n >\n <ng-container *ngIf=\"message?.status === 'sending'; else sentStatus\">\n <ng-container *ngTemplateOutlet=\"sendingStatus\"></ng-container>\n </ng-container>\n <ng-template #sentStatus>\n <ng-container\n *ngIf=\"\n mode === 'main' &&\n isMessageDeliveredAndRead &&\n canDisplayReadStatus;\n else deliveredStatus\n \"\n >\n <ng-container *ngTemplateOutlet=\"readStatus\"></ng-container>\n </ng-container>\n </ng-template>\n </ng-container>\n <stream-avatar\n data-testid=\"avatar\"\n class=\"str-chat-angular__avatar-host\"\n [imageUrl]=\"message?.user?.image\"\n [name]=\"message?.user?.name || message?.user?.id\"\n ></stream-avatar>\n <div class=\"str-chat__message-inner\">\n <div\n class=\"str-chat__message-simple__actions\"\n data-testid=\"message-options\"\n *ngIf=\"areOptionsVisible\"\n >\n <div\n data-testid=\"message-actions-container\"\n class=\"\n str-chat__message-simple__actions__action\n str-chat__message-simple__actions__action--options\n \"\n [class.str-chat-angular__message-simple__actions__action--options--editing]=\"\n isEditing\n \"\n >\n <stream-message-actions-box\n [isOpen]=\"isActionBoxOpen\"\n [isMine]=\"isSentByCurrentUser\"\n [enabledActions]=\"enabledMessageActions\"\n [message]=\"message\"\n (displayedActionsCount)=\"visibleMessageActionsCount = $event\"\n (isEditing)=\"isEditing = $event; isActionBoxOpen = !isEditing\"\n [messageInputTemplate]=\"messageInputTemplate\"\n ></stream-message-actions-box>\n <stream-icon\n *ngIf=\"visibleMessageActionsCount > 0\"\n data-testid=\"action-icon\"\n icon=\"action-icon\"\n (keyup.enter)=\"isActionBoxOpen = !isActionBoxOpen\"\n (click)=\"isActionBoxOpen = !isActionBoxOpen\"\n ></stream-icon>\n </div>\n <!-- eslint-disable @angular-eslint/template/conditional-complexity -->\n <div\n *ngIf=\"\n enabledMessageActions.indexOf('send-reply') !== -1 &&\n mode === 'main'\n \"\n class=\"\n str-chat__message-simple__actions__action\n str-chat__message-simple__actions__action--thread\n \"\n data-testid=\"reply-in-thread\"\n (click)=\"setAsActiveParentMessage()\"\n (keyup.enter)=\"setAsActiveParentMessage()\"\n >\n <stream-icon icon=\"reply-in-thread\"></stream-icon>\n </div>\n <div\n *ngIf=\"\n areReactionsEnabled !== false &&\n canReactToMessage !== false &&\n enabledMessageActions.indexOf('send-reaction') !== -1\n \"\n class=\"\n str-chat__message-simple__actions__action\n str-chat__message-simple__actions__action--reactions\n \"\n data-testid=\"reaction-icon\"\n (click)=\"isReactionSelectorOpen = !isReactionSelectorOpen\"\n (keyup.enter)=\"isReactionSelectorOpen = !isReactionSelectorOpen\"\n >\n <stream-icon icon=\"reaction-icon\"></stream-icon>\n </div>\n </div>\n <!-- eslint-enable @angular-eslint/template/conditional-complexity -->\n <stream-message-reactions\n *ngIf=\"areReactionsEnabled !== false\"\n [messageReactionCounts]=\"message?.reaction_counts || {}\"\n [latestReactions]=\"message?.latest_reactions || []\"\n [(isSelectorOpen)]=\"isReactionSelectorOpen\"\n [messageId]=\"message?.id\"\n [ownReactions]=\"message?.own_reactions || []\"\n ></stream-message-reactions>\n <stream-attachment-list\n *ngIf=\"hasAttachment && !message?.quoted_message\"\n [attachments]=\"message!.attachments!\"\n [messageId]=\"message!.id\"\n ></stream-attachment-list>\n <div class=\"str-chat__message-text\" *ngIf=\"message?.text\">\n <div\n data-testid=\"inner-message\"\n class=\"\n str-chat__message-text-inner str-chat__message-simple-text-inner\n \"\n [class.str-chat__message-light-text-inner--has-attachment]=\"\n hasAttachment\n \"\n (click)=\"\n message?.status === 'failed' && message?.errorStatusCode !== 403\n ? resendMessage()\n : undefined\n \"\n (keyup.enter)=\"\n message?.status === 'failed' && message?.errorStatusCode !== 403\n ? resendMessage()\n : undefined\n \"\n >\n <ng-container *ngTemplateOutlet=\"quotedMessage\"></ng-container>\n <stream-attachment-list\n *ngIf=\"hasAttachment && message?.quoted_message\"\n [attachments]=\"message!.attachments!\"\n [messageId]=\"message!.id\"\n ></stream-attachment-list>\n <div\n data-testid=\"client-error-message\"\n *ngIf=\"message?.type === 'error'\"\n class=\"str-chat__simple-message--error-message\"\n >\n {{ \"streamChat.Error \u00B7 Unsent\" | translate }}\n </div>\n <div\n data-testid=\"error-message\"\n *ngIf=\"message?.status === 'failed'\"\n class=\"str-chat__simple-message--error-message\"\n >\n {{\n (message?.errorStatusCode === 403\n ? \"streamChat.Message Failed \u00B7 Unauthorized\"\n : \"streamChat.Message Failed \u00B7 Click to try again\"\n ) | translate\n }}\n </div>\n <div\n (click)=\"textClicked()\"\n (keyup.enter)=\"textClicked()\"\n data-testid=\"text\"\n >\n <p>\n <!-- eslint-disable-next-line @angular-eslint/template/use-track-by-function -->\n <ng-container *ngFor=\"let part of messageTextParts\">\n <span\n *ngIf=\"part.type === 'text'; else mention\"\n [innerHTML]=\"part.content\"\n ></span>\n <ng-template #mention>\n <ng-container *ngIf=\"mentionTemplate; else defaultMention\">\n <ng-container\n *ngTemplateOutlet=\"\n mentionTemplate;\n context: { user: part.user! }\n \"\n ></ng-container>\n </ng-container>\n <ng-template #defaultMention>\n <b>{{ part.content }}</b>\n </ng-template>\n </ng-template>\n </ng-container>\n </p>\n </div>\n </div>\n </div>\n <div class=\"str-chat__message-simple-reply-button\">\n <button\n *ngIf=\"\n !!message?.reply_count &&\n mode !== 'thread' &&\n enabledMessageActions.indexOf('send-reply') !== -1\n \"\n class=\"str-chat__message-replies-count-button\"\n data-testid=\"reply-count-button\"\n (click)=\"setAsActiveParentMessage()\"\n >\n <stream-icon icon=\"reply\"></stream-icon>\n {{message?.reply_count === 1 ? ('streamChat.1 reply' | translate) : ('streamChat.{{ replyCount }}\n replies' | translate:replyCountParam)}}\n </button>\n </div>\n <div class=\"str-chat__message-data str-chat__message-simple-data\">\n <span\n data-testid=\"sender\"\n *ngIf=\"!isSentByCurrentUser\"\n class=\"str-chat__message-simple-name\"\n >\n {{ message?.user?.name ? message?.user?.name : message?.user?.id }}\n </span>\n <span data-testid=\"date\" class=\"str-chat__message-simple-timestamp\">\n {{ parsedDate }}\n </span>\n </div>\n </div>\n </ng-container>\n </ng-container>\n</div>\n\n<ng-template #sendingStatus>\n <span\n class=\"\n str-chat__message-simple-status str-chat__message-simple-status-angular\n \"\n data-testid=\"sending-indicator\"\n >\n <div class=\"str-chat__tooltip\">\n {{ \"streamChat.Sending...\" | translate }}\n </div>\n <stream-loading-indicator\n data-testid=\"loading-indicator\"\n ></stream-loading-indicator>\n </span>\n</ng-template>\n<ng-template #readStatus>\n <span\n class=\"\n str-chat__message-simple-status str-chat__message-simple-status-angular\n \"\n data-testid=\"read-indicator\"\n >\n <div class=\"str-chat__tooltip\" data-testid=\"read-by-tooltip\">\n {{ readByText }}\n </div>\n <stream-avatar\n class=\"str-chat-angular__avatar-host\"\n data-test-id=\"last-read-user-avatar\"\n [size]=\"15\"\n [imageUrl]=\"lastReadUser?.image\"\n [name]=\"lastReadUser?.name || lastReadUser?.id\"\n ></stream-avatar>\n <span\n data-test-id=\"read-by-length\"\n *ngIf=\"isReadByMultipleUsers\"\n class=\"str-chat__message-simple-status-number\"\n >\n {{ (message?.readBy)!.length }}\n </span>\n </span>\n</ng-template>\n<ng-template #deliveredStatus>\n <span\n *ngIf=\"mode === 'main'\"\n class=\"\n str-chat__message-simple-status str-chat__message-simple-status-angular\n \"\n data-testid=\"delivered-indicator\"\n >\n <div class=\"str-chat__tooltip\">\n {{ \"streamChat.Delivered\" | translate }}\n </div>\n <stream-icon\n data-testid=\"delivered-icon\"\n icon=\"delivered-icon\"\n ></stream-icon>\n </span>\n</ng-template>\n\n<ng-template #deletedMessage>\n <div data-testid=\"message-deleted-component\">\n <div class=\"str-chat__message--deleted-inner\" translate>\n streamChat.This message was deleted...\n </div>\n </div>\n</ng-template>\n\n<ng-template #systemMessage>\n <div data-testid=\"system-message\" class=\"str-chat__message--system\">\n <div class=\"str-chat__message--system__text\">\n <div class=\"str-chat__message--system__line\"></div>\n <p>{{ message?.text }}</p>\n <div class=\"str-chat__message--system__line\"></div>\n </div>\n <div class=\"str-chat__message--system__date\">\n {{ parsedDate }}\n </div>\n </div>\n</ng-template>\n\n<ng-template #quotedMessage>\n <div\n *ngIf=\"message?.quoted_message\"\n class=\"quoted-message\"\n data-testid=\"quoted-message-container\"\n [class.mine]=\"isSentByCurrentUser\"\n >\n <stream-avatar\n data-testid=\"qouted-message-avatar\"\n class=\"str-chat-angular__avatar-host\"\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 ></stream-avatar>\n <div class=\"quoted-message-inner\">\n <stream-attachment-list\n *ngIf=\"\n message?.quoted_message?.attachments &&\n message?.quoted_message?.attachments?.length\n \"\n [attachments]=\"quotedMessageAttachments\"\n [messageId]=\"message?.quoted_message?.id\"\n ></stream-attachment-list>\n <div\n data-testid=\"quoted-message-text\"\n [innerHTML]=\"\n message?.quoted_message?.html || message?.quoted_message?.text\n \"\n ></div>\n </div>\n </div>\n</ng-template>\n", components: [{ type: AvatarComponent, selector: "stream-avatar", inputs: ["name", "imageUrl", "size"] }, { type: MessageActionsBoxComponent, selector: "stream-message-actions-box", inputs: ["messageInputTemplate", "isOpen", "isMine", "message", "enabledActions"], outputs: ["displayedActionsCount", "isEditing"] }, { type: IconComponent, selector: "stream-icon", inputs: ["icon", "size"] }, { type: MessageReactionsComponent, selector: "stream-message-reactions", inputs: ["messageId", "messageReactionCounts", "isSelectorOpen", "latestReactions", "ownReactions"], outputs: ["isSelectorOpenChange"] }, { type: AttachmentListComponent, selector: "stream-attachment-list", inputs: ["messageId", "attachments"] }, { type: LoadingIndicatorComponent, selector: "stream-loading-indicator", inputs: ["size", "color"] }], directives: [{ type: i6.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i6.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet"] }, { type: i6.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i2.TranslateDirective, selector: "[translate],[ngx-translate]", inputs: ["translate", "translateParams"] }], pipes: { "translate": i2.TranslatePipe } });
|
|
3549
|
+
MessageComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: MessageComponent, deps: [{ token: ChatClientService }, { token: ChannelService }, { token: CustomTemplatesService }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
|
|
3550
|
+
MessageComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.5", type: MessageComponent, selector: "stream-message", inputs: { message: "message", enabledMessageActions: "enabledMessageActions", isLastSentMessage: "isLastSentMessage", mode: "mode" }, viewQueries: [{ propertyName: "container", first: true, predicate: ["container"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div\n #container\n class=\"str-chat__message-simple str-chat__message str-chat__message--{{\n message?.type\n }} str-chat__message--{{ message?.status }} {{\n message?.text ? 'str-chat__message--has-text' : 'has-no-text'\n }}\"\n [class.str-chat__message--me]=\"isSentByCurrentUser\"\n [class.str-chat__message-simple--me]=\"isSentByCurrentUser\"\n [class.mobile-press]=\"isPressedOnMobile\"\n [class.str-chat__message--has-attachment]=\"hasAttachment\"\n [class.str-chat__message--with-reactions]=\"hasReactions\"\n data-testid=\"message-container\"\n (mouseleave)=\"isActionBoxOpen = false\"\n>\n <ng-container *ngIf=\"!message?.deleted_at; else deletedMessage\">\n <ng-container *ngIf=\"message?.type !== 'system'; else systemMessage\">\n <ng-container\n *ngIf=\"\n isSentByCurrentUser &&\n ((isLastSentMessage && message?.status === 'received') ||\n message?.status === 'sending')\n \"\n >\n <ng-container *ngIf=\"message?.status === 'sending'; else sentStatus\">\n <ng-container *ngTemplateOutlet=\"sendingStatus\"></ng-container>\n </ng-container>\n <ng-template #sentStatus>\n <ng-container\n *ngIf=\"\n mode === 'main' &&\n isMessageDeliveredAndRead &&\n canDisplayReadStatus;\n else deliveredStatus\n \"\n >\n <ng-container *ngTemplateOutlet=\"readStatus\"></ng-container>\n </ng-container>\n </ng-template>\n </ng-container>\n <stream-avatar-placeholder\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-placeholder>\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 <ng-template\n #defaultMessageActionsBox\n let-isOpen=\"isOpen\"\n let-isMine=\"isMine\"\n let-enabledActions=\"enabledActions\"\n let-messageInput=\"message\"\n let-displayedActionsCountChaneHanler=\"displayedActionsCountChaneHanler\"\n let-isEditingChangeHandler=\"isEditingChangeHandler\"\n >\n <stream-message-actions-box\n [isOpen]=\"isOpen\"\n [isMine]=\"isMine\"\n [enabledActions]=\"enabledActions\"\n [message]=\"messageInput\"\n (displayedActionsCount)=\"\n displayedActionsCountChaneHanler($event)\n \"\n (isEditing)=\"isEditingChangeHandler($event)\"\n ></stream-message-actions-box>\n </ng-template>\n <ng-container\n *ngTemplateOutlet=\"\n messageActionsBoxTemplate || defaultMessageActionsBox;\n context: getMessageActionsBoxContext()\n \"\n ></ng-container>\n <stream-icon-placeholder\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-placeholder>\n </div>\n <!-- eslint-disable @angular-eslint/template/conditional-complexity -->\n <div\n *ngIf=\"\n enabledMessageActions.indexOf('send-reply') !== -1 &&\n mode === 'main'\n \"\n class=\"\n str-chat__message-simple__actions__action\n str-chat__message-simple__actions__action--thread\n \"\n data-testid=\"reply-in-thread\"\n (click)=\"setAsActiveParentMessage()\"\n (keyup.enter)=\"setAsActiveParentMessage()\"\n >\n <stream-icon-placeholder\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 \"\n data-testid=\"reaction-icon\"\n (click)=\"isReactionSelectorOpen = !isReactionSelectorOpen\"\n (keyup.enter)=\"isReactionSelectorOpen = !isReactionSelectorOpen\"\n >\n <stream-icon-placeholder\n icon=\"reaction-icon\"\n ></stream-icon-placeholder>\n </div>\n </div>\n <!-- eslint-enable @angular-eslint/template/conditional-complexity -->\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 messageReactionsTemplate || defaultMessageReactions;\n context: getMessageReactionsContext()\n \"\n ></ng-container>\n <ng-container *ngIf=\"hasAttachment && !message?.quoted_message\">\n <ng-template\n #defaultAttachments\n let-messageId=\"messageId\"\n let-attachments=\"attachments\"\n >\n <stream-attachment-list\n [messageId]=\"messageId\"\n [attachments]=\"attachments\"\n ></stream-attachment-list>\n </ng-template>\n <ng-container\n *ngTemplateOutlet=\"\n attachmentListTemplate || defaultAttachments;\n context: getAttachmentListContext()\n \"\n ></ng-container>\n </ng-container>\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 <ng-container *ngTemplateOutlet=\"quotedMessage\"></ng-container>\n <stream-attachment-list\n *ngIf=\"hasAttachment && message?.quoted_message\"\n [attachments]=\"message!.attachments!\"\n [messageId]=\"message!.id\"\n ></stream-attachment-list>\n <div\n data-testid=\"client-error-message\"\n *ngIf=\"message?.type === 'error'\"\n class=\"str-chat__simple-message--error-message\"\n >\n {{ \"streamChat.Error \u00B7 Unsent\" | translate }}\n </div>\n <div\n data-testid=\"error-message\"\n *ngIf=\"message?.status === 'failed'\"\n class=\"str-chat__simple-message--error-message\"\n >\n {{\n (message?.errorStatusCode === 403\n ? \"streamChat.Message Failed \u00B7 Unauthorized\"\n : \"streamChat.Message Failed \u00B7 Click to try again\"\n ) | translate\n }}\n </div>\n <div\n (click)=\"textClicked()\"\n (keyup.enter)=\"textClicked()\"\n data-testid=\"text\"\n >\n <p>\n <!-- eslint-disable-next-line @angular-eslint/template/use-track-by-function -->\n <ng-container *ngFor=\"let part of messageTextParts\">\n <span\n *ngIf=\"part.type === 'text'; else mention\"\n [innerHTML]=\"part.content\"\n ></span>\n <ng-template #mention>\n <ng-template #defaultMention let-content=\"content\">\n <b>{{ content }}</b>\n </ng-template>\n <ng-container\n *ngTemplateOutlet=\"\n mentionTemplate || defaultMention;\n context: getMentionContext(part)\n \"\n ></ng-container>\n </ng-template>\n </ng-container>\n </p>\n </div>\n </div>\n </div>\n <div class=\"str-chat__message-simple-reply-button\">\n <button\n *ngIf=\"\n !!message?.reply_count &&\n mode !== 'thread' &&\n enabledMessageActions.indexOf('send-reply') !== -1\n \"\n class=\"str-chat__message-replies-count-button\"\n data-testid=\"reply-count-button\"\n (click)=\"setAsActiveParentMessage()\"\n >\n <stream-icon-placeholder icon=\"reply\"></stream-icon-placeholder>\n {{message?.reply_count === 1 ? ('streamChat.1 reply' | translate) : ('streamChat.{{ replyCount }}\n replies' | translate:replyCountParam)}}\n </button>\n </div>\n <div class=\"str-chat__message-data str-chat__message-simple-data\">\n <span\n data-testid=\"sender\"\n *ngIf=\"!isSentByCurrentUser\"\n class=\"str-chat__message-simple-name\"\n >\n {{ message?.user?.name ? message?.user?.name : message?.user?.id }}\n </span>\n <span data-testid=\"date\" class=\"str-chat__message-simple-timestamp\">\n {{ parsedDate }}\n </span>\n </div>\n </div>\n </ng-container>\n </ng-container>\n</div>\n\n<ng-template #sendingStatus>\n <span\n class=\"\n str-chat__message-simple-status str-chat__message-simple-status-angular\n \"\n data-testid=\"sending-indicator\"\n >\n <div class=\"str-chat__tooltip\">\n {{ \"streamChat.Sending...\" | translate }}\n </div>\n <stream-loading-indicator-placeholder\n data-testid=\"loading-indicator\"\n ></stream-loading-indicator-placeholder>\n </span>\n</ng-template>\n<ng-template #readStatus>\n <span\n class=\"\n str-chat__message-simple-status str-chat__message-simple-status-angular\n \"\n data-testid=\"read-indicator\"\n >\n <div class=\"str-chat__tooltip\" data-testid=\"read-by-tooltip\">\n {{ readByText }}\n </div>\n <stream-avatar-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 ></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-template #deliveredStatus>\n <span\n *ngIf=\"mode === 'main'\"\n class=\"\n str-chat__message-simple-status str-chat__message-simple-status-angular\n \"\n data-testid=\"delivered-indicator\"\n >\n <div class=\"str-chat__tooltip\">\n {{ \"streamChat.Delivered\" | translate }}\n </div>\n <stream-icon-placeholder\n data-testid=\"delivered-icon\"\n icon=\"delivered-icon\"\n ></stream-icon-placeholder>\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\n<ng-template #quotedMessage>\n <div\n *ngIf=\"message?.quoted_message\"\n class=\"quoted-message\"\n data-testid=\"quoted-message-container\"\n [class.mine]=\"isSentByCurrentUser\"\n >\n <stream-avatar-placeholder\n data-testid=\"qouted-message-avatar\"\n class=\"str-chat-angular__avatar-host\"\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 ></stream-avatar-placeholder>\n <div class=\"quoted-message-inner\">\n <stream-attachment-list\n *ngIf=\"\n message?.quoted_message?.attachments &&\n message?.quoted_message?.attachments?.length\n \"\n [attachments]=\"quotedMessageAttachments\"\n [messageId]=\"message?.quoted_message?.id\"\n ></stream-attachment-list>\n <div\n data-testid=\"quoted-message-text\"\n [innerHTML]=\"\n message?.quoted_message?.html || message?.quoted_message?.text\n \"\n ></div>\n </div>\n </div>\n</ng-template>\n", components: [{ type: AvatarPlaceholderComponent, selector: "stream-avatar-placeholder", inputs: ["name", "imageUrl", "size"] }, { type: MessageActionsBoxComponent, selector: "stream-message-actions-box", inputs: ["isOpen", "isMine", "message", "enabledActions"], 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", "attachments"] }, { type: LoadingIndicatorPlaceholderComponent, selector: "stream-loading-indicator-placeholder", inputs: ["size", "color"] }], directives: [{ type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i3.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet"] }, { type: i3.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i2.TranslateDirective, selector: "[translate],[ngx-translate]", inputs: ["translate", "translateParams"] }], pipes: { "translate": i2.TranslatePipe } });
|
|
3218
3551
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: MessageComponent, decorators: [{
|
|
3219
3552
|
type: Component,
|
|
3220
3553
|
args: [{
|
|
@@ -3222,22 +3555,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImpor
|
|
|
3222
3555
|
templateUrl: './message.component.html',
|
|
3223
3556
|
styles: [],
|
|
3224
3557
|
}]
|
|
3225
|
-
}], ctorParameters: function () { return [{ type: ChatClientService }, { type: ChannelService }]; }, propDecorators: {
|
|
3226
|
-
type: Input
|
|
3227
|
-
}], mentionTemplate: [{
|
|
3228
|
-
type: Input
|
|
3229
|
-
}], message: [{
|
|
3558
|
+
}], ctorParameters: function () { return [{ type: ChatClientService }, { type: ChannelService }, { type: CustomTemplatesService }, { type: i0.ChangeDetectorRef }]; }, propDecorators: { message: [{
|
|
3230
3559
|
type: Input
|
|
3231
3560
|
}], enabledMessageActions: [{
|
|
3232
3561
|
type: Input
|
|
3233
|
-
}], areReactionsEnabled: [{
|
|
3234
|
-
type: Input
|
|
3235
|
-
}], canReactToMessage: [{
|
|
3236
|
-
type: Input
|
|
3237
3562
|
}], isLastSentMessage: [{
|
|
3238
3563
|
type: Input
|
|
3239
|
-
}], canReceiveReadEvents: [{
|
|
3240
|
-
type: Input
|
|
3241
3564
|
}], mode: [{
|
|
3242
3565
|
type: Input
|
|
3243
3566
|
}], container: [{
|
|
@@ -3336,11 +3659,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImpor
|
|
|
3336
3659
|
* The `AutocompleteTextarea` component is used by the [`MessageInput`](./MessageInputComponent.mdx) component to display the input HTML element where users can type their message.
|
|
3337
3660
|
*/
|
|
3338
3661
|
class AutocompleteTextareaComponent {
|
|
3339
|
-
constructor(channelService, chatClientService, transliterationService, emojiInputService) {
|
|
3662
|
+
constructor(channelService, chatClientService, transliterationService, emojiInputService, customTemplatesService) {
|
|
3340
3663
|
this.channelService = channelService;
|
|
3341
3664
|
this.chatClientService = chatClientService;
|
|
3342
3665
|
this.transliterationService = transliterationService;
|
|
3343
3666
|
this.emojiInputService = emojiInputService;
|
|
3667
|
+
this.customTemplatesService = customTemplatesService;
|
|
3344
3668
|
this.class = 'str-chat__textarea';
|
|
3345
3669
|
/**
|
|
3346
3670
|
* The value of the input HTML element.
|
|
@@ -3416,6 +3740,8 @@ class AutocompleteTextareaComponent {
|
|
|
3416
3740
|
selectionStart + emoji.length;
|
|
3417
3741
|
this.inputChanged();
|
|
3418
3742
|
}));
|
|
3743
|
+
this.subscriptions.push(this.customTemplatesService.mentionAutocompleteItemTemplate$.subscribe((template) => (this.mentionAutocompleteItemTemplate = template)));
|
|
3744
|
+
this.subscriptions.push(this.customTemplatesService.commandAutocompleteItemTemplate$.subscribe((template) => (this.commandAutocompleteItemTemplate = template)));
|
|
3419
3745
|
this.autocompleteConfig.mentions = [
|
|
3420
3746
|
this.userMentionConfig,
|
|
3421
3747
|
this.slashCommandConfig,
|
|
@@ -3514,8 +3840,8 @@ class AutocompleteTextareaComponent {
|
|
|
3514
3840
|
}
|
|
3515
3841
|
}
|
|
3516
3842
|
}
|
|
3517
|
-
AutocompleteTextareaComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: AutocompleteTextareaComponent, deps: [{ token: ChannelService }, { token: ChatClientService }, { token: TransliterationService }, { token: EmojiInputService }], target: i0.ɵɵFactoryTarget.Component });
|
|
3518
|
-
AutocompleteTextareaComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.5", type: AutocompleteTextareaComponent, selector: "stream-autocomplete-textarea", inputs: { value: "value", areMentionsEnabled: "areMentionsEnabled",
|
|
3843
|
+
AutocompleteTextareaComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: AutocompleteTextareaComponent, deps: [{ token: ChannelService }, { token: ChatClientService }, { token: TransliterationService }, { token: EmojiInputService }, { token: CustomTemplatesService }], target: i0.ɵɵFactoryTarget.Component });
|
|
3844
|
+
AutocompleteTextareaComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.5", type: AutocompleteTextareaComponent, selector: "stream-autocomplete-textarea", inputs: { value: "value", areMentionsEnabled: "areMentionsEnabled", mentionScope: "mentionScope" }, outputs: { valueChange: "valueChange", send: "send", userMentions: "userMentions" }, host: { properties: { "class": "this.class" } }, viewQueries: [{ propertyName: "messageInput", first: true, predicate: ["input"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<textarea\n [value]=\"value || ''\"\n autofocus\n data-testid=\"textarea\"\n #input\n placeholder=\"{{ 'streamChat.Type your message' | translate }}\"\n class=\"rta__textarea str-chat__textarea__textarea str-chat__angular-textarea\"\n rows=\"1\"\n (input)=\"inputChanged()\"\n (keydown.enter)=\"sent($event)\"\n [mentionConfig]=\"autocompleteConfig\"\n (searchTerm)=\"autcompleteSearchTermChanged($event)\"\n [mentionListTemplate]=\"autocompleteItem\"\n (blur)=\"inputLeft()\"\n></textarea>\n<ng-template #autocompleteItem let-item=\"item\">\n <div class=\"rta rta__item str-chat__emojisearch__item\" [ngSwitch]=\"item.type\">\n <div class=\"rta__entity\" *ngSwitchCase=\"'mention'\">\n <ng-container\n *ngTemplateOutlet=\"\n mentionAutocompleteItemTemplate || defaultMentionTemplate;\n context: { item: item }\n \"\n ></ng-container>\n </div>\n <div class=\"rta__entity\" *ngSwitchCase=\"'command'\">\n <ng-container\n *ngTemplateOutlet=\"\n commandAutocompleteItemTemplate || defaultCommandTemplate;\n context: { item: item }\n \"\n ></ng-container>\n </div>\n </div>\n</ng-template>\n\n<ng-template #defaultCommandTemplate let-item=\"item\">\n <div class=\"str-chat__slash-command\">\n <span class=\"str-chat__slash-command-header\">\n <strong data-testclass=\"command-name\">{{ item.name }}</strong>\n {{ item.args }}\n </span>\n <br />\n <span class=\"str-chat__slash-command-description\">{{\n item.description\n }}</span>\n </div>\n</ng-template>\n\n<ng-template #defaultMentionTemplate let-item=\"item\">\n <div class=\"str-chat__user-item\">\n <stream-avatar-placeholder\n data-testclass=\"avatar\"\n class=\"str-chat__avatar str-chat__avatar--circle\"\n style=\"height: 20px\"\n [size]=\"20\"\n [imageUrl]=\"item.image || item.user?.image\"\n [name]=\"item.autocompleteLabel\"\n ></stream-avatar-placeholder>\n <span data-testclass=\"username\" class=\"str-chat__user-item--name\">{{\n item.autocompleteLabel\n }}</span>\n </div>\n</ng-template>\n", components: [{ type: AvatarPlaceholderComponent, selector: "stream-avatar-placeholder", inputs: ["name", "imageUrl", "size"] }], directives: [{ type: i7.MentionDirective, selector: "[mention], [mentionConfig]", inputs: ["mentionConfig", "mention", "mentionListTemplate"], outputs: ["searchTerm", "itemSelected", "opened", "closed"] }, { type: i3.NgSwitch, selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { type: i3.NgSwitchCase, selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }, { type: i3.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet"] }], pipes: { "translate": i2.TranslatePipe } });
|
|
3519
3845
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: AutocompleteTextareaComponent, decorators: [{
|
|
3520
3846
|
type: Component,
|
|
3521
3847
|
args: [{
|
|
@@ -3523,16 +3849,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImpor
|
|
|
3523
3849
|
templateUrl: './autocomplete-textarea.component.html',
|
|
3524
3850
|
styles: [],
|
|
3525
3851
|
}]
|
|
3526
|
-
}], ctorParameters: function () { return [{ type: ChannelService }, { type: ChatClientService }, { type: TransliterationService }, { type: EmojiInputService }]; }, propDecorators: { class: [{
|
|
3852
|
+
}], ctorParameters: function () { return [{ type: ChannelService }, { type: ChatClientService }, { type: TransliterationService }, { type: EmojiInputService }, { type: CustomTemplatesService }]; }, propDecorators: { class: [{
|
|
3527
3853
|
type: HostBinding
|
|
3528
3854
|
}], value: [{
|
|
3529
3855
|
type: Input
|
|
3530
3856
|
}], areMentionsEnabled: [{
|
|
3531
3857
|
type: Input
|
|
3532
|
-
}], mentionAutocompleteItemTemplate: [{
|
|
3533
|
-
type: Input
|
|
3534
|
-
}], commandAutocompleteItemTemplate: [{
|
|
3535
|
-
type: Input
|
|
3536
3858
|
}], mentionScope: [{
|
|
3537
3859
|
type: Input
|
|
3538
3860
|
}], valueChange: [{
|
|
@@ -3590,19 +3912,11 @@ const isOnSameDay = (date1, date2) => {
|
|
|
3590
3912
|
* The `MessageList` component renders a scrollable list of messages.
|
|
3591
3913
|
*/
|
|
3592
3914
|
class MessageListComponent {
|
|
3593
|
-
constructor(channelService, chatClientService, imageLoadService) {
|
|
3915
|
+
constructor(channelService, chatClientService, imageLoadService, customTemplatesService) {
|
|
3594
3916
|
this.channelService = channelService;
|
|
3595
3917
|
this.chatClientService = chatClientService;
|
|
3596
3918
|
this.imageLoadService = imageLoadService;
|
|
3597
|
-
|
|
3598
|
-
* @deprecated use [channel capabilities](https://getstream.io/chat/docs/javascript/channel_capabilities/?language=javascript) instead. If true, the message reactions are displayed. Users can also react to messages if they have the necessary [channel capability](https://getstream.io/chat/docs/javascript/channel_capabilities/?language=javascript).
|
|
3599
|
-
*/
|
|
3600
|
-
this.areReactionsEnabled = undefined;
|
|
3601
|
-
/**
|
|
3602
|
-
* @deprecated use [channel capabilities](https://getstream.io/chat/docs/javascript/channel_capabilities/?language=javascript) instead. The list of [actions that are enabled](./MessageActionsBoxComponent.mdx), please note that the user also has to have the necessary [channel capabilities](https://getstream.io/chat/docs/javascript/channel_capabilities/?language=javascript) for actions to work. Unathorized actions won't be displayed on the UI. The `MessgaeList` component makes the necessary checks before passing the actions to the `Message` component.
|
|
3603
|
-
*/
|
|
3604
|
-
/* eslint-disable-next-line @angular-eslint/no-input-rename */
|
|
3605
|
-
this.enabledMessageActionsInput = undefined;
|
|
3919
|
+
this.customTemplatesService = customTemplatesService;
|
|
3606
3920
|
/**
|
|
3607
3921
|
* Determines if the message list should display channel messages or [thread messages](https://getstream.io/chat/docs/javascript/threads/?language=javascript).
|
|
3608
3922
|
*/
|
|
@@ -3611,7 +3925,6 @@ class MessageListComponent {
|
|
|
3611
3925
|
this.class = 'str-chat-angular__main-panel-inner str-chat-angular__message-list-host';
|
|
3612
3926
|
this.unreadMessageCount = 0;
|
|
3613
3927
|
this.groupStyles = [];
|
|
3614
|
-
this.authorizedMessageActions = ['flag'];
|
|
3615
3928
|
this.isUserScrolledUpThreshold = 300;
|
|
3616
3929
|
this.subscriptions = [];
|
|
3617
3930
|
this.subscriptions.push(this.channelService.activeChannel$.subscribe((channel) => {
|
|
@@ -3619,39 +3932,7 @@ class MessageListComponent {
|
|
|
3619
3932
|
this.resetScrollState();
|
|
3620
3933
|
const capabilites = (_a = channel === null || channel === void 0 ? void 0 : channel.data) === null || _a === void 0 ? void 0 : _a.own_capabilities;
|
|
3621
3934
|
if (capabilites) {
|
|
3622
|
-
this.
|
|
3623
|
-
this.canReceiveReadEvents = capabilites.indexOf('read-events') !== -1;
|
|
3624
|
-
this.authorizedMessageActions = [];
|
|
3625
|
-
if (this.canReactToMessage) {
|
|
3626
|
-
this.authorizedMessageActions.push('send-reaction');
|
|
3627
|
-
}
|
|
3628
|
-
if (this.canReceiveReadEvents) {
|
|
3629
|
-
this.authorizedMessageActions.push('read-events');
|
|
3630
|
-
}
|
|
3631
|
-
if (capabilites.indexOf('flag-message') !== -1) {
|
|
3632
|
-
this.authorizedMessageActions.push('flag');
|
|
3633
|
-
}
|
|
3634
|
-
if (capabilites.indexOf('update-own-message') !== -1) {
|
|
3635
|
-
this.authorizedMessageActions.push('edit');
|
|
3636
|
-
}
|
|
3637
|
-
if (capabilites.indexOf('update-any-message') !== -1) {
|
|
3638
|
-
this.authorizedMessageActions.push('edit');
|
|
3639
|
-
this.authorizedMessageActions.push('edit-any');
|
|
3640
|
-
}
|
|
3641
|
-
if (capabilites.indexOf('delete-own-message') !== -1) {
|
|
3642
|
-
this.authorizedMessageActions.push('delete');
|
|
3643
|
-
}
|
|
3644
|
-
if (capabilites.indexOf('delete-any-message') !== -1) {
|
|
3645
|
-
this.authorizedMessageActions.push('delete');
|
|
3646
|
-
this.authorizedMessageActions.push('delete-any');
|
|
3647
|
-
}
|
|
3648
|
-
if (capabilites.indexOf('send-reply') !== -1) {
|
|
3649
|
-
this.authorizedMessageActions.push('send-reply');
|
|
3650
|
-
}
|
|
3651
|
-
if (capabilites.indexOf('quote-message') !== -1) {
|
|
3652
|
-
this.authorizedMessageActions.push('quote-message');
|
|
3653
|
-
}
|
|
3654
|
-
this.setEnabledActions();
|
|
3935
|
+
this.enabledMessageActions = capabilites;
|
|
3655
3936
|
}
|
|
3656
3937
|
}));
|
|
3657
3938
|
this.subscriptions.push(this.imageLoadService.imageLoad$.subscribe(() => {
|
|
@@ -3672,6 +3953,8 @@ class MessageListComponent {
|
|
|
3672
3953
|
}
|
|
3673
3954
|
this.parentMessage = message;
|
|
3674
3955
|
}));
|
|
3956
|
+
this.subscriptions.push(this.customTemplatesService.messageTemplate$.subscribe((template) => (this.messageTemplate = template)));
|
|
3957
|
+
this.subscriptions.push(this.customTemplatesService.typingIndicatorTemplate$.subscribe((template) => (this.typingIndicatorTemplate = template)));
|
|
3675
3958
|
this.usersTypingInChannel$ = this.channelService.usersTypingInChannel$;
|
|
3676
3959
|
this.usersTypingInThread$ = this.channelService.usersTypingInThread$;
|
|
3677
3960
|
}
|
|
@@ -3679,9 +3962,6 @@ class MessageListComponent {
|
|
|
3679
3962
|
this.setMessages$();
|
|
3680
3963
|
}
|
|
3681
3964
|
ngOnChanges(changes) {
|
|
3682
|
-
if (changes.enabledMessageActionsInput) {
|
|
3683
|
-
this.setEnabledActions();
|
|
3684
|
-
}
|
|
3685
3965
|
if (changes.mode) {
|
|
3686
3966
|
this.setMessages$();
|
|
3687
3967
|
}
|
|
@@ -3713,11 +3993,6 @@ class MessageListComponent {
|
|
|
3713
3993
|
ngOnDestroy() {
|
|
3714
3994
|
this.subscriptions.forEach((s) => s.unsubscribe());
|
|
3715
3995
|
}
|
|
3716
|
-
get usersTyping$() {
|
|
3717
|
-
return this.mode === 'thread'
|
|
3718
|
-
? this.usersTypingInThread$
|
|
3719
|
-
: this.usersTypingInChannel$;
|
|
3720
|
-
}
|
|
3721
3996
|
trackByMessageId(index, item) {
|
|
3722
3997
|
return item.id;
|
|
3723
3998
|
}
|
|
@@ -3750,31 +4025,24 @@ class MessageListComponent {
|
|
|
3750
4025
|
}
|
|
3751
4026
|
this.prevScrollTop = this.scrollContainer.nativeElement.scrollTop;
|
|
3752
4027
|
}
|
|
4028
|
+
getTypingIndicatorContext() {
|
|
4029
|
+
return {
|
|
4030
|
+
usersTyping$: this.usersTyping$,
|
|
4031
|
+
};
|
|
4032
|
+
}
|
|
4033
|
+
getMessageContext(message) {
|
|
4034
|
+
return {
|
|
4035
|
+
message,
|
|
4036
|
+
isLastSentMessage: !!(this.lastSentMessageId && (message === null || message === void 0 ? void 0 : message.id) === this.lastSentMessageId),
|
|
4037
|
+
enabledMessageActions: this.enabledMessageActions,
|
|
4038
|
+
mode: this.mode,
|
|
4039
|
+
};
|
|
4040
|
+
}
|
|
3753
4041
|
preserveScrollbarPosition() {
|
|
3754
4042
|
this.scrollContainer.nativeElement.scrollTop =
|
|
3755
4043
|
(this.prevScrollTop || 0) +
|
|
3756
4044
|
(this.scrollContainer.nativeElement.scrollHeight - this.containerHeight);
|
|
3757
4045
|
}
|
|
3758
|
-
setEnabledActions() {
|
|
3759
|
-
this.enabledMessageActions = [];
|
|
3760
|
-
if (!this.enabledMessageActionsInput) {
|
|
3761
|
-
this.enabledMessageActions = this.authorizedMessageActions;
|
|
3762
|
-
return;
|
|
3763
|
-
}
|
|
3764
|
-
this.enabledMessageActionsInput = [
|
|
3765
|
-
...this.enabledMessageActionsInput,
|
|
3766
|
-
'send-reaction',
|
|
3767
|
-
'read-events',
|
|
3768
|
-
'send-reply',
|
|
3769
|
-
'quote-message',
|
|
3770
|
-
];
|
|
3771
|
-
this.enabledMessageActionsInput.forEach((action) => {
|
|
3772
|
-
const isAuthorized = this.authorizedMessageActions.indexOf(action) !== -1;
|
|
3773
|
-
if (isAuthorized) {
|
|
3774
|
-
this.enabledMessageActions.push(action);
|
|
3775
|
-
}
|
|
3776
|
-
});
|
|
3777
|
-
}
|
|
3778
4046
|
setMessages$() {
|
|
3779
4047
|
this.messages$ = (this.mode === 'main'
|
|
3780
4048
|
? this.channelService.activeChannelMessages$
|
|
@@ -3827,9 +4095,14 @@ class MessageListComponent {
|
|
|
3827
4095
|
this.prevScrollTop = undefined;
|
|
3828
4096
|
this.isNewMessageSentByUser = undefined;
|
|
3829
4097
|
}
|
|
4098
|
+
get usersTyping$() {
|
|
4099
|
+
return this.mode === 'thread'
|
|
4100
|
+
? this.usersTypingInThread$
|
|
4101
|
+
: this.usersTypingInChannel$;
|
|
4102
|
+
}
|
|
3830
4103
|
}
|
|
3831
|
-
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 });
|
|
3832
|
-
MessageListComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.5", type: MessageListComponent, selector: "stream-message-list", inputs: {
|
|
4104
|
+
MessageListComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: MessageListComponent, deps: [{ token: ChannelService }, { token: ChatClientService }, { token: ImageLoadService }, { token: CustomTemplatesService }], target: i0.ɵɵFactoryTarget.Component });
|
|
4105
|
+
MessageListComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.5", type: MessageListComponent, selector: "stream-message-list", inputs: { mode: "mode" }, host: { properties: { "class": "this.class" } }, viewQueries: [{ propertyName: "scrollContainer", first: true, predicate: ["scrollContainer"], descendants: true }, { propertyName: "parentMessageElement", first: true, predicate: ["parentMessageElement"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div\n #scrollContainer\n data-testid=\"scroll-container\"\n class=\"str-chat__list\"\n (scroll)=\"scrolled()\"\n>\n <div class=\"str-chat__reverse-infinite-scroll\">\n <ul class=\"str-chat__ul\">\n <li\n #parentMessageElement\n *ngIf=\"mode === 'thread'\"\n data-testid=\"parent-message\"\n >\n <ng-container\n *ngTemplateOutlet=\"\n messageTemplateContainer;\n context: { message: parentMessage }\n \"\n ></ng-container>\n <div class=\"str-chat__thread-start\" translate>\n streamChat.Start of a new thread\n </div>\n </li>\n <li\n data-testclass=\"message\"\n *ngFor=\"\n let message of messages$ | async;\n let i = index;\n trackBy: trackByMessageId\n \"\n class=\"str-chat__li str-chat__li--{{ groupStyles[i] }}\"\n >\n <ng-container\n *ngTemplateOutlet=\"\n messageTemplateContainer;\n context: { message: message }\n \"\n ></ng-container>\n </li>\n </ul>\n <ng-template #defaultTypingIndicator let-usersTyping$=\"usersTyping$\">\n <div\n *ngIf=\"$any(usersTyping$ | async)?.length\"\n data-testid=\"typing-indicator\"\n class=\"str-chat__typing-indicator str-chat__typing-indicator--typing\"\n >\n <stream-avatar-placeholder\n *ngFor=\"let user of usersTyping$ | async; trackBy: trackByUserId\"\n [name]=\"user.name || user.id\"\n [imageUrl]=\"user.image\"\n ></stream-avatar-placeholder>\n <div class=\"str-chat__typing-indicator__dots\">\n <span class=\"str-chat__typing-indicator__dot\"></span>\n <span class=\"str-chat__typing-indicator__dot\"></span>\n <span class=\"str-chat__typing-indicator__dot\"></span>\n </div>\n </div>\n </ng-template>\n <ng-container\n *ngTemplateOutlet=\"\n typingIndicatorTemplate || defaultTypingIndicator;\n context: getTypingIndicatorContext()\n \"\n ></ng-container>\n </div>\n</div>\n<div class=\"str-chat__list-notifications\">\n <button\n data-testid=\"scroll-to-bottom\"\n *ngIf=\"isUserScrolledUp\"\n class=\"\n str-chat__message-notification\n str-chat__message-notification-right\n str-chat__message-notification-scroll-down\n \"\n (keyup.enter)=\"scrollToBottom()\"\n (click)=\"scrollToBottom()\"\n >\n <div\n *ngIf=\"unreadMessageCount > 0\"\n class=\"\n str-chat__message-notification\n str-chat__message-notification-scroll-down-unread-count\n \"\n >\n {{ unreadMessageCount }}\n </div>\n </button>\n</div>\n\n<ng-template #messageTemplateContainer let-message=\"message\">\n <ng-template\n #defaultMessageTemplate\n let-messageInput=\"message\"\n let-isLastSentMessage=\"isLastSentMessage\"\n let-enabledMessageActions=\"enabledMessageActions\"\n let-mode=\"mode\"\n >\n <stream-message\n [message]=\"messageInput\"\n [isLastSentMessage]=\"isLastSentMessage\"\n [enabledMessageActions]=\"enabledMessageActions\"\n [mode]=\"mode\"\n ></stream-message>\n </ng-template>\n <ng-container\n *ngTemplateOutlet=\"\n messageTemplate || defaultMessageTemplate;\n context: getMessageContext(message)\n \"\n ></ng-container>\n</ng-template>\n", components: [{ type: AvatarPlaceholderComponent, selector: "stream-avatar-placeholder", inputs: ["name", "imageUrl", "size"] }, { type: MessageComponent, selector: "stream-message", inputs: ["message", "enabledMessageActions", "isLastSentMessage", "mode"] }], directives: [{ type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i3.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet"] }, { type: i2.TranslateDirective, selector: "[translate],[ngx-translate]", inputs: ["translate", "translateParams"] }, { type: i3.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }], pipes: { "async": i3.AsyncPipe } });
|
|
3833
4106
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: MessageListComponent, decorators: [{
|
|
3834
4107
|
type: Component,
|
|
3835
4108
|
args: [{
|
|
@@ -3837,20 +4110,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImpor
|
|
|
3837
4110
|
templateUrl: './message-list.component.html',
|
|
3838
4111
|
styles: [],
|
|
3839
4112
|
}]
|
|
3840
|
-
}], ctorParameters: function () { return [{ type: ChannelService }, { type: ChatClientService }, { type: ImageLoadService }]; }, propDecorators: {
|
|
3841
|
-
type: Input
|
|
3842
|
-
}], messageInputTemplate: [{
|
|
3843
|
-
type: Input
|
|
3844
|
-
}], mentionTemplate: [{
|
|
3845
|
-
type: Input
|
|
3846
|
-
}], typingIndicatorTemplate: [{
|
|
3847
|
-
type: Input
|
|
3848
|
-
}], areReactionsEnabled: [{
|
|
3849
|
-
type: Input
|
|
3850
|
-
}], enabledMessageActionsInput: [{
|
|
3851
|
-
type: Input,
|
|
3852
|
-
args: ['enabledMessageActions']
|
|
3853
|
-
}], mode: [{
|
|
4113
|
+
}], ctorParameters: function () { return [{ type: ChannelService }, { type: ChatClientService }, { type: ImageLoadService }, { type: CustomTemplatesService }]; }, propDecorators: { mode: [{
|
|
3854
4114
|
type: Input
|
|
3855
4115
|
}], class: [{
|
|
3856
4116
|
type: HostBinding,
|
|
@@ -3867,7 +4127,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImpor
|
|
|
3867
4127
|
* The `Thread` component represents a [message thread](https://getstream.io/chat/docs/javascript/threads/?language=javascript), it is a container component that displays a thread with a header, [`MessageList`](./MessageListComponent.mdx) and [`MessageInput`](./MessageInputComponent.mdx) components.
|
|
3868
4128
|
*/
|
|
3869
4129
|
class ThreadComponent {
|
|
3870
|
-
constructor(channelService) {
|
|
4130
|
+
constructor(customTemplatesService, channelService) {
|
|
4131
|
+
this.customTemplatesService = customTemplatesService;
|
|
3871
4132
|
this.channelService = channelService;
|
|
3872
4133
|
this.class = 'str-chat__thread';
|
|
3873
4134
|
this.subscriptions = [];
|
|
@@ -3876,16 +4137,21 @@ class ThreadComponent {
|
|
|
3876
4137
|
ngOnDestroy() {
|
|
3877
4138
|
this.subscriptions.forEach((s) => s.unsubscribe());
|
|
3878
4139
|
}
|
|
3879
|
-
|
|
3880
|
-
|
|
3881
|
-
|
|
4140
|
+
getThreadHeaderContext() {
|
|
4141
|
+
return {
|
|
4142
|
+
parentMessage: this.parentMessage,
|
|
4143
|
+
closeThreadHandler: () => this.closeThread(),
|
|
4144
|
+
};
|
|
4145
|
+
}
|
|
4146
|
+
getReplyCountParam(parentMessage) {
|
|
4147
|
+
return { replyCount: parentMessage === null || parentMessage === void 0 ? void 0 : parentMessage.reply_count };
|
|
3882
4148
|
}
|
|
3883
4149
|
closeThread() {
|
|
3884
4150
|
void this.channelService.setAsActiveParentMessage(undefined);
|
|
3885
4151
|
}
|
|
3886
4152
|
}
|
|
3887
|
-
ThreadComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: ThreadComponent, deps: [{ token: ChannelService }], target: i0.ɵɵFactoryTarget.Component });
|
|
3888
|
-
ThreadComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.5", type: ThreadComponent, selector: "stream-thread", host: { properties: { "class": "this.class" } }, ngImport: i0, template: "<div class=\"str-chat__thread-header\">\n
|
|
4153
|
+
ThreadComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: ThreadComponent, deps: [{ token: CustomTemplatesService }, { token: ChannelService }], target: i0.ɵɵFactoryTarget.Component });
|
|
4154
|
+
ThreadComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.5", type: ThreadComponent, selector: "stream-thread", host: { properties: { "class": "this.class" } }, ngImport: i0, template: "<ng-container\n *ngTemplateOutlet=\"\n (customTemplatesService.threadHeaderTemplate$ | async) ||\n defaultThreadHeader;\n context: getThreadHeaderContext()\n \"\n></ng-container>\n<ng-content select='[name=\"thread-message-list\"]'></ng-content>\n<div class=\"str-chat__small-message-input__wrapper\">\n <ng-content select='[name=\"thread-message-input\"]'></ng-content>\n</div>\n\n<ng-template\n #defaultThreadHeader\n let-parentMessage=\"parentMessage\"\n let-closeThreadHandler=\"closeThreadHandler\"\n>\n <div class=\"str-chat__thread-header\">\n <div class=\"str-chat__thread-header-details\">\n <strong translate>streamChat.Thread</strong>\n <small data-testid=\"reply-count\">\n {{parentMessage?.reply_count === 1 ? ('streamChat.1 reply' | translate) : ('streamChat.{{ replyCount }}\n replies' | translate:getReplyCountParam(parentMessage))}}\n </small>\n </div>\n <button\n class=\"str-chat__square-button\"\n data-testid=\"close-button\"\n (click)=\"closeThreadHandler()\"\n >\n <stream-icon-placeholder\n icon=\"close-no-outline\"\n ></stream-icon-placeholder>\n </button>\n </div>\n</ng-template>\n", components: [{ type: IconPlaceholderComponent, selector: "stream-icon-placeholder", inputs: ["icon", "size"] }], directives: [{ type: i3.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet"] }, { type: i2.TranslateDirective, selector: "[translate],[ngx-translate]", inputs: ["translate", "translateParams"] }], pipes: { "async": i3.AsyncPipe, "translate": i2.TranslatePipe } });
|
|
3889
4155
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: ThreadComponent, decorators: [{
|
|
3890
4156
|
type: Component,
|
|
3891
4157
|
args: [{
|
|
@@ -3893,7 +4159,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImpor
|
|
|
3893
4159
|
templateUrl: './thread.component.html',
|
|
3894
4160
|
styles: [],
|
|
3895
4161
|
}]
|
|
3896
|
-
}], ctorParameters: function () { return [{ type: ChannelService }]; }, propDecorators: { class: [{
|
|
4162
|
+
}], ctorParameters: function () { return [{ type: CustomTemplatesService }, { type: ChannelService }]; }, propDecorators: { class: [{
|
|
3897
4163
|
type: HostBinding,
|
|
3898
4164
|
args: ['class']
|
|
3899
4165
|
}] } });
|
|
@@ -3901,14 +4167,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImpor
|
|
|
3901
4167
|
class StreamAvatarModule {
|
|
3902
4168
|
}
|
|
3903
4169
|
StreamAvatarModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: StreamAvatarModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
3904
|
-
StreamAvatarModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: StreamAvatarModule, declarations: [AvatarComponent], imports: [CommonModule, TranslateModule], exports: [AvatarComponent] });
|
|
4170
|
+
StreamAvatarModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: StreamAvatarModule, declarations: [AvatarComponent, AvatarPlaceholderComponent], imports: [CommonModule, TranslateModule], exports: [AvatarComponent, AvatarPlaceholderComponent] });
|
|
3905
4171
|
StreamAvatarModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: StreamAvatarModule, imports: [[CommonModule, TranslateModule]] });
|
|
3906
4172
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: StreamAvatarModule, decorators: [{
|
|
3907
4173
|
type: NgModule,
|
|
3908
4174
|
args: [{
|
|
3909
|
-
declarations: [AvatarComponent],
|
|
4175
|
+
declarations: [AvatarComponent, AvatarPlaceholderComponent],
|
|
3910
4176
|
imports: [CommonModule, TranslateModule],
|
|
3911
|
-
exports: [AvatarComponent],
|
|
4177
|
+
exports: [AvatarComponent, AvatarPlaceholderComponent],
|
|
3912
4178
|
}]
|
|
3913
4179
|
}] });
|
|
3914
4180
|
|
|
@@ -3932,7 +4198,9 @@ StreamChatModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "12.0.0", versio
|
|
|
3932
4198
|
AttachmentPreviewListComponent,
|
|
3933
4199
|
ModalComponent,
|
|
3934
4200
|
TextareaDirective,
|
|
3935
|
-
ThreadComponent
|
|
4201
|
+
ThreadComponent,
|
|
4202
|
+
IconPlaceholderComponent,
|
|
4203
|
+
LoadingIndicatorPlaceholderComponent], imports: [CommonModule, TranslateModule, StreamAvatarModule], exports: [ChannelComponent,
|
|
3936
4204
|
ChannelHeaderComponent,
|
|
3937
4205
|
ChannelListComponent,
|
|
3938
4206
|
ChannelPreviewComponent,
|
|
@@ -3949,7 +4217,9 @@ StreamChatModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "12.0.0", versio
|
|
|
3949
4217
|
AttachmentPreviewListComponent,
|
|
3950
4218
|
ModalComponent,
|
|
3951
4219
|
StreamAvatarModule,
|
|
3952
|
-
ThreadComponent
|
|
4220
|
+
ThreadComponent,
|
|
4221
|
+
IconPlaceholderComponent,
|
|
4222
|
+
LoadingIndicatorPlaceholderComponent] });
|
|
3953
4223
|
StreamChatModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: StreamChatModule, imports: [[CommonModule, TranslateModule, StreamAvatarModule], StreamAvatarModule] });
|
|
3954
4224
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: StreamChatModule, decorators: [{
|
|
3955
4225
|
type: NgModule,
|
|
@@ -3973,6 +4243,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImpor
|
|
|
3973
4243
|
ModalComponent,
|
|
3974
4244
|
TextareaDirective,
|
|
3975
4245
|
ThreadComponent,
|
|
4246
|
+
IconPlaceholderComponent,
|
|
4247
|
+
LoadingIndicatorPlaceholderComponent,
|
|
3976
4248
|
],
|
|
3977
4249
|
imports: [CommonModule, TranslateModule, StreamAvatarModule],
|
|
3978
4250
|
exports: [
|
|
@@ -3994,6 +4266,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImpor
|
|
|
3994
4266
|
ModalComponent,
|
|
3995
4267
|
StreamAvatarModule,
|
|
3996
4268
|
ThreadComponent,
|
|
4269
|
+
IconPlaceholderComponent,
|
|
4270
|
+
LoadingIndicatorPlaceholderComponent,
|
|
3997
4271
|
],
|
|
3998
4272
|
}]
|
|
3999
4273
|
}] });
|
|
@@ -4056,5 +4330,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImpor
|
|
|
4056
4330
|
* Generated bundle index. Do not edit.
|
|
4057
4331
|
*/
|
|
4058
4332
|
|
|
4059
|
-
export { AttachmentListComponent, AttachmentPreviewListComponent, AttachmentService, AutocompleteTextareaComponent, AvatarComponent, ChannelComponent, ChannelHeaderComponent, ChannelListComponent, ChannelListToggleService, ChannelPreviewComponent, ChannelService, ChatClientService, EmojiInputService, IconComponent, ImageLoadService, LoadingIndicatorComponent, MessageActionsBoxComponent, MessageComponent, MessageInputComponent, MessageInputConfigService, MessageListComponent, MessageReactionsComponent, ModalComponent, NotificationComponent, NotificationListComponent, NotificationService, StreamAutocompleteTextareaModule, StreamAvatarModule, StreamChatModule, StreamI18nService, StreamTextareaModule, TextareaComponent, TextareaDirective, ThemeService, ThreadComponent, TransliterationService, createMessagePreview, getDeviceWidth, getGroupStyles, getReadBy, getReadByText, isImageAttachment, isImageFile, parseDate, textareaInjectionToken };
|
|
4333
|
+
export { AttachmentListComponent, AttachmentPreviewListComponent, AttachmentService, AutocompleteTextareaComponent, AvatarComponent, AvatarPlaceholderComponent, ChannelComponent, ChannelHeaderComponent, ChannelListComponent, ChannelListToggleService, ChannelPreviewComponent, ChannelService, ChatClientService, CustomTemplatesService, EmojiInputService, IconComponent, IconPlaceholderComponent, ImageLoadService, LoadingIndicatorComponent, LoadingIndicatorPlaceholderComponent, MessageActionsBoxComponent, MessageComponent, MessageInputComponent, MessageInputConfigService, MessageListComponent, MessageReactionsComponent, ModalComponent, NotificationComponent, NotificationListComponent, NotificationService, StreamAutocompleteTextareaModule, StreamAvatarModule, StreamChatModule, StreamI18nService, StreamTextareaModule, TextareaComponent, TextareaDirective, ThemeService, ThreadComponent, TransliterationService, createMessagePreview, getDeviceWidth, getGroupStyles, getReadBy, getReadByText, isImageAttachment, isImageFile, parseDate, textareaInjectionToken };
|
|
4060
4334
|
//# sourceMappingURL=stream-chat-angular.js.map
|