stream-chat-angular 2.12.3 → 2.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/assets/version.d.ts +1 -1
- package/bundles/stream-chat-angular.umd.js +450 -55
- package/bundles/stream-chat-angular.umd.js.map +1 -1
- package/esm2015/assets/version.js +2 -2
- package/esm2015/lib/attachment.service.js +29 -1
- package/esm2015/lib/channel-list/channel-list-toggle.service.js +20 -1
- package/esm2015/lib/channel.service.js +146 -3
- package/esm2015/lib/chat-client.service.js +25 -1
- package/esm2015/lib/message/message.component.js +5 -1
- package/esm2015/lib/message-actions-box/message-actions-box.component.js +1 -1
- package/esm2015/lib/message-input/autocomplete-textarea/autocomplete-textarea.component.js +21 -9
- package/esm2015/lib/message-input/emoji-input.service.js +23 -0
- package/esm2015/lib/message-input/message-input-config.service.js +16 -1
- package/esm2015/lib/message-input/message-input.component.js +36 -20
- package/esm2015/lib/message-input/textarea/textarea.component.js +22 -6
- package/esm2015/lib/message-list/image-load.service.js +7 -1
- package/esm2015/lib/message-list/message-list.component.js +18 -5
- package/esm2015/lib/message-reactions/message-reactions.component.js +2 -2
- package/esm2015/lib/notification.service.js +19 -1
- package/esm2015/lib/stream-i18n.service.js +9 -1
- package/esm2015/lib/theme.service.js +23 -1
- package/esm2015/lib/transliteration.service.js +9 -1
- package/esm2015/public-api.js +2 -1
- package/fesm2015/stream-chat-angular.js +406 -40
- package/fesm2015/stream-chat-angular.js.map +1 -1
- package/lib/attachment.service.d.ts +34 -0
- package/lib/channel-list/channel-list-toggle.service.d.ts +22 -0
- package/lib/channel.service.d.ts +172 -0
- package/lib/chat-client.service.d.ts +39 -0
- package/lib/message-input/autocomplete-textarea/autocomplete-textarea.component.d.ts +3 -1
- package/lib/message-input/emoji-input.service.d.ts +14 -0
- package/lib/message-input/message-input-config.service.d.ts +27 -1
- package/lib/message-input/message-input.component.d.ts +8 -3
- package/lib/message-input/textarea/textarea.component.d.ts +7 -3
- package/lib/message-list/image-load.service.d.ts +6 -0
- package/lib/message-list/message-list.component.d.ts +10 -2
- package/lib/notification.service.d.ts +21 -0
- package/lib/stream-i18n.service.d.ts +8 -0
- package/lib/theme.service.d.ts +22 -0
- package/lib/transliteration.service.d.ts +8 -0
- package/package.json +4 -3
- package/public-api.d.ts +1 -0
- package/src/assets/version.ts +1 -1
|
@@ -5,24 +5,36 @@ import { BehaviorSubject, ReplaySubject, combineLatest, Subject, of } from 'rxjs
|
|
|
5
5
|
import { StreamChat } from 'stream-chat';
|
|
6
6
|
import { map, shareReplay, filter, first, catchError, startWith, distinctUntilChanged, debounceTime, tap } from 'rxjs/operators';
|
|
7
7
|
import { v4 } from 'uuid';
|
|
8
|
-
import * as
|
|
8
|
+
import * as i2 from '@ngx-translate/core';
|
|
9
9
|
import { TranslateModule } from '@ngx-translate/core';
|
|
10
10
|
import * as i6 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
|
+
import emojiRegex from 'emoji-regex';
|
|
15
16
|
import transliterate from '@stream-io/transliterate';
|
|
16
|
-
import * as
|
|
17
|
+
import * as i6$1 from 'angular-mentions';
|
|
17
18
|
import { MentionModule } from 'angular-mentions';
|
|
18
19
|
|
|
19
|
-
const version = '2.
|
|
20
|
+
const version = '2.14.0';
|
|
20
21
|
|
|
22
|
+
/**
|
|
23
|
+
* The `NotificationService` can be used to add or remove notifications. By default the [`NotificationList`](../components/notifications.mdx) component displays the currently active notifications.
|
|
24
|
+
*/
|
|
21
25
|
class NotificationService {
|
|
22
26
|
constructor() {
|
|
23
27
|
this.notificationsSubject = new BehaviorSubject([]);
|
|
24
28
|
this.notifications$ = this.notificationsSubject.asObservable();
|
|
25
29
|
}
|
|
30
|
+
/**
|
|
31
|
+
* Displays a notification for the given amount of time.
|
|
32
|
+
* @param text The text of the notification
|
|
33
|
+
* @param type The type of the notification
|
|
34
|
+
* @param timeout The number of milliseconds while the notification should be visible
|
|
35
|
+
* @param translateParams Translation parameters for the `text`
|
|
36
|
+
* @returns A method to clear the notification (before the timeout).
|
|
37
|
+
*/
|
|
26
38
|
addTemporaryNotification(text, type = 'error', timeout = 5000, translateParams) {
|
|
27
39
|
this.addNotification(text, type, translateParams);
|
|
28
40
|
const id = setTimeout(() => this.removeNotification(text), timeout);
|
|
@@ -31,6 +43,13 @@ class NotificationService {
|
|
|
31
43
|
this.removeNotification(text);
|
|
32
44
|
};
|
|
33
45
|
}
|
|
46
|
+
/**
|
|
47
|
+
* Displays a notification, that will be visible until it's removed.
|
|
48
|
+
* @param text The text of the notification
|
|
49
|
+
* @param type The type of the notification
|
|
50
|
+
* @param translateParams Translation parameters for the `text`
|
|
51
|
+
* @returns A method to clear the notification.
|
|
52
|
+
*/
|
|
34
53
|
addPermanentNotification(text, type = 'error', translateParams) {
|
|
35
54
|
this.addNotification(text, type, translateParams);
|
|
36
55
|
return () => this.removeNotification(text);
|
|
@@ -60,6 +79,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImpor
|
|
|
60
79
|
}]
|
|
61
80
|
}], ctorParameters: function () { return []; } });
|
|
62
81
|
|
|
82
|
+
/**
|
|
83
|
+
* The `ChatClient` service connects the user to the Stream chat.
|
|
84
|
+
*/
|
|
63
85
|
class ChatClientService {
|
|
64
86
|
constructor(ngZone, notificationService) {
|
|
65
87
|
this.ngZone = ngZone;
|
|
@@ -71,6 +93,12 @@ class ChatClientService {
|
|
|
71
93
|
this.connectionState$ = this.connectionStateSubject.asObservable();
|
|
72
94
|
this.appSettings$ = this.appSettingsSubject.asObservable();
|
|
73
95
|
}
|
|
96
|
+
/**
|
|
97
|
+
* Creates a [`StreamChat`](https://github.com/GetStream/stream-chat-js/blob/668b3e5521339f4e14fc657834531b4c8bf8176b/src/client.ts#L124) instance using the provided `apiKey`, and connects a user with the given meta data and token. More info about [connecting users](https://getstream.io/chat/docs/javascript/init_and_users/?language=javascript) can be found in the platform documentation.
|
|
98
|
+
* @param apiKey
|
|
99
|
+
* @param userOrId
|
|
100
|
+
* @param userTokenOrProvider
|
|
101
|
+
*/
|
|
74
102
|
init(apiKey, userOrId, userTokenOrProvider) {
|
|
75
103
|
return __awaiter(this, void 0, void 0, function* () {
|
|
76
104
|
this.chatClient = StreamChat.getInstance(apiKey);
|
|
@@ -105,11 +133,17 @@ class ChatClientService {
|
|
|
105
133
|
});
|
|
106
134
|
});
|
|
107
135
|
}
|
|
136
|
+
/**
|
|
137
|
+
* Disconnects the current user, and closes the WebSocket connection. Useful when disconnecting a chat user, use in combination with [`reset`](./ChannelService.mdx/#reset).
|
|
138
|
+
*/
|
|
108
139
|
disconnectUser() {
|
|
109
140
|
return __awaiter(this, void 0, void 0, function* () {
|
|
110
141
|
yield this.chatClient.disconnectUser();
|
|
111
142
|
});
|
|
112
143
|
}
|
|
144
|
+
/**
|
|
145
|
+
* Loads the current [application settings](https://getstream.io/chat/docs/javascript/app_setting_overview/?language=javascript), if the application settings have already been loaded, it does nothing.
|
|
146
|
+
*/
|
|
113
147
|
getAppSettings() {
|
|
114
148
|
return __awaiter(this, void 0, void 0, function* () {
|
|
115
149
|
if (this.appSettingsSubject.getValue()) {
|
|
@@ -119,11 +153,20 @@ class ChatClientService {
|
|
|
119
153
|
this.appSettingsSubject.next(settings.app || {});
|
|
120
154
|
});
|
|
121
155
|
}
|
|
156
|
+
/**
|
|
157
|
+
* Flag the message with the given ID. If you want to know [more about flags](https://getstream.io/chat/docs/javascript/moderation/?language=javascript) check out the platform documentation.
|
|
158
|
+
* @param messageId
|
|
159
|
+
*/
|
|
122
160
|
flagMessage(messageId) {
|
|
123
161
|
return __awaiter(this, void 0, void 0, function* () {
|
|
124
162
|
yield this.chatClient.flagMessage(messageId);
|
|
125
163
|
});
|
|
126
164
|
}
|
|
165
|
+
/**
|
|
166
|
+
* Searches for users in the application that have ID or name matching the provided search term
|
|
167
|
+
* @param searchTerm
|
|
168
|
+
* @returns The users matching the search
|
|
169
|
+
*/
|
|
127
170
|
autocompleteUsers(searchTerm) {
|
|
128
171
|
return __awaiter(this, void 0, void 0, function* () {
|
|
129
172
|
if (!searchTerm) {
|
|
@@ -181,6 +224,9 @@ const getReadBy = (message, channel) => {
|
|
|
181
224
|
return readBy;
|
|
182
225
|
};
|
|
183
226
|
|
|
227
|
+
/**
|
|
228
|
+
* The `ChannelService` provides data and interaction for the channel list and message list. TEST
|
|
229
|
+
*/
|
|
184
230
|
class ChannelService {
|
|
185
231
|
constructor(chatClientService, ngZone) {
|
|
186
232
|
this.chatClientService = chatClientService;
|
|
@@ -194,6 +240,8 @@ class ChannelService {
|
|
|
194
240
|
this.activeThreadMessagesSubject = new BehaviorSubject([]);
|
|
195
241
|
this.messagePageSize = 25;
|
|
196
242
|
this.messageToQuoteSubject = new BehaviorSubject(undefined);
|
|
243
|
+
this.usersTypingInChannelSubject = new BehaviorSubject([]);
|
|
244
|
+
this.usersTypingInThreadSubject = new BehaviorSubject([]);
|
|
197
245
|
this.channelListSetter = (channels) => {
|
|
198
246
|
this.channelsSubject.next(channels);
|
|
199
247
|
};
|
|
@@ -236,7 +284,14 @@ class ChannelService {
|
|
|
236
284
|
.subscribe(() => {
|
|
237
285
|
void this.setAsActiveParentMessage(undefined);
|
|
238
286
|
});
|
|
239
|
-
|
|
287
|
+
this.usersTypingInChannel$ =
|
|
288
|
+
this.usersTypingInChannelSubject.asObservable();
|
|
289
|
+
this.usersTypingInThread$ = this.usersTypingInThreadSubject.asObservable();
|
|
290
|
+
}
|
|
291
|
+
/**
|
|
292
|
+
* Sets the given `channel` as active.
|
|
293
|
+
* @param channel
|
|
294
|
+
*/
|
|
240
295
|
setAsActiveChannel(channel) {
|
|
241
296
|
const prevActiveChannel = this.activeChannelSubject.getValue();
|
|
242
297
|
this.stopWatchForActiveChannelEvents(prevActiveChannel);
|
|
@@ -253,6 +308,10 @@ class ChannelService {
|
|
|
253
308
|
this.activeThreadMessagesSubject.next([]);
|
|
254
309
|
this.messageToQuoteSubject.next(undefined);
|
|
255
310
|
}
|
|
311
|
+
/**
|
|
312
|
+
* Sets the given `message` as an active parent message. If `undefined` is provided, it will deleselect the current parent message.
|
|
313
|
+
* @param message
|
|
314
|
+
*/
|
|
256
315
|
setAsActiveParentMessage(message) {
|
|
257
316
|
var _a;
|
|
258
317
|
return __awaiter(this, void 0, void 0, function* () {
|
|
@@ -274,7 +333,9 @@ class ChannelService {
|
|
|
274
333
|
}
|
|
275
334
|
});
|
|
276
335
|
}
|
|
277
|
-
|
|
336
|
+
/**
|
|
337
|
+
* Loads the next page of messages of the active channel. The page size can be set in the [query option](https://getstream.io/chat/docs/javascript/query_channels/?language=javascript#query-options) object.
|
|
338
|
+
*/
|
|
278
339
|
loadMoreMessages() {
|
|
279
340
|
var _a, _b, _c, _d, _e;
|
|
280
341
|
return __awaiter(this, void 0, void 0, function* () {
|
|
@@ -293,6 +354,9 @@ class ChannelService {
|
|
|
293
354
|
}
|
|
294
355
|
});
|
|
295
356
|
}
|
|
357
|
+
/**
|
|
358
|
+
* Loads the next page of messages of the active thread. The page size can be set in the [query option](https://getstream.io/chat/docs/javascript/query_channels/?language=javascript#query-options) object.
|
|
359
|
+
*/
|
|
296
360
|
loadMoreThreadReplies() {
|
|
297
361
|
var _a, _b;
|
|
298
362
|
return __awaiter(this, void 0, void 0, function* () {
|
|
@@ -309,6 +373,12 @@ class ChannelService {
|
|
|
309
373
|
this.activeThreadMessagesSubject.next((activeChnannel === null || activeChnannel === void 0 ? void 0 : activeChnannel.state.threads[parentMessageId]) || []);
|
|
310
374
|
});
|
|
311
375
|
}
|
|
376
|
+
/**
|
|
377
|
+
* Queries the channels with the given filters, sorts and options. More info about [channel querying](https://getstream.io/chat/docs/javascript/query_channels/?language=javascript) can be found in the platform documentation.
|
|
378
|
+
* @param filters
|
|
379
|
+
* @param sort
|
|
380
|
+
* @param options
|
|
381
|
+
*/
|
|
312
382
|
init(filters, sort, options) {
|
|
313
383
|
return __awaiter(this, void 0, void 0, function* () {
|
|
314
384
|
this.filters = filters;
|
|
@@ -325,6 +395,9 @@ class ChannelService {
|
|
|
325
395
|
this.chatClientService.notification$.subscribe((notification) => void this.handleNotification(notification));
|
|
326
396
|
});
|
|
327
397
|
}
|
|
398
|
+
/**
|
|
399
|
+
* Resets the `activeChannel$`, `channels$` and `activeChannelMessages$` Observables. Useful when disconnecting a chat user, use in combination with [`disconnectUser`](./chat-client.mdx/#disconnectuser).
|
|
400
|
+
*/
|
|
328
401
|
reset() {
|
|
329
402
|
this.activeChannelMessagesSubject.next([]);
|
|
330
403
|
this.activeChannelSubject.next(undefined);
|
|
@@ -333,12 +406,20 @@ class ChannelService {
|
|
|
333
406
|
this.channelsSubject.next(undefined);
|
|
334
407
|
this.selectMessageToQuote(undefined);
|
|
335
408
|
}
|
|
409
|
+
/**
|
|
410
|
+
* Loads the next page of channels. The page size can be set in the [query option](https://getstream.io/chat/docs/javascript/query_channels/?language=javascript#query-options) object.
|
|
411
|
+
*/
|
|
336
412
|
loadMoreChannels() {
|
|
337
413
|
return __awaiter(this, void 0, void 0, function* () {
|
|
338
414
|
this.options.offset = this.channels.length;
|
|
339
415
|
yield this.queryChannels();
|
|
340
416
|
});
|
|
341
417
|
}
|
|
418
|
+
/**
|
|
419
|
+
* Adds a reaction to a message.
|
|
420
|
+
* @param messageId The id of the message to add the reaction to
|
|
421
|
+
* @param reactionType The type of the reaction
|
|
422
|
+
*/
|
|
342
423
|
addReaction(messageId, reactionType) {
|
|
343
424
|
var _a;
|
|
344
425
|
return __awaiter(this, void 0, void 0, function* () {
|
|
@@ -347,6 +428,11 @@ class ChannelService {
|
|
|
347
428
|
}));
|
|
348
429
|
});
|
|
349
430
|
}
|
|
431
|
+
/**
|
|
432
|
+
* Removes a reaction from a message.
|
|
433
|
+
* @param messageId The id of the message to remove the reaction from
|
|
434
|
+
* @param reactionType Thr type of reaction to remove
|
|
435
|
+
*/
|
|
350
436
|
removeReaction(messageId, reactionType) {
|
|
351
437
|
var _a;
|
|
352
438
|
return __awaiter(this, void 0, void 0, function* () {
|
|
@@ -354,6 +440,14 @@ class ChannelService {
|
|
|
354
440
|
.getValue()) === null || _a === void 0 ? void 0 : _a.deleteReaction(messageId, reactionType));
|
|
355
441
|
});
|
|
356
442
|
}
|
|
443
|
+
/**
|
|
444
|
+
* Sends a message to the active channel. The message is immediately added to the message list, if an error occurs and the message can't be sent, the error is indicated in `state` of the message.
|
|
445
|
+
* @param text The text of the message
|
|
446
|
+
* @param attachments The attachments
|
|
447
|
+
* @param mentionedUsers Mentioned users
|
|
448
|
+
* @param parentId Id of the parent message (if sending a thread reply)
|
|
449
|
+
* @param quotedMessageId Id of the message to quote (if sending a quote reply)
|
|
450
|
+
*/
|
|
357
451
|
sendMessage(text, attachments = [], mentionedUsers = [], parentId = undefined, quotedMessageId = undefined) {
|
|
358
452
|
return __awaiter(this, void 0, void 0, function* () {
|
|
359
453
|
const preview = createMessagePreview(this.chatClientService.chatClient.user, text, attachments, mentionedUsers, parentId, quotedMessageId);
|
|
@@ -363,6 +457,10 @@ class ChannelService {
|
|
|
363
457
|
yield this.sendMessageRequest(preview);
|
|
364
458
|
});
|
|
365
459
|
}
|
|
460
|
+
/**
|
|
461
|
+
* Resends the given message to the active channel
|
|
462
|
+
* @param message The message to resend
|
|
463
|
+
*/
|
|
366
464
|
resendMessage(message) {
|
|
367
465
|
return __awaiter(this, void 0, void 0, function* () {
|
|
368
466
|
const channel = this.activeChannelSubject.getValue();
|
|
@@ -370,16 +468,29 @@ class ChannelService {
|
|
|
370
468
|
yield this.sendMessageRequest(message);
|
|
371
469
|
});
|
|
372
470
|
}
|
|
471
|
+
/**
|
|
472
|
+
* Updates the message in the active channel
|
|
473
|
+
* @param message Mesage to be updated
|
|
474
|
+
*/
|
|
373
475
|
updateMessage(message) {
|
|
374
476
|
return __awaiter(this, void 0, void 0, function* () {
|
|
375
477
|
yield this.chatClientService.chatClient.updateMessage(message);
|
|
376
478
|
});
|
|
377
479
|
}
|
|
480
|
+
/**
|
|
481
|
+
* Deletes the message from the active channel
|
|
482
|
+
* @param message Message to be deleted
|
|
483
|
+
*/
|
|
378
484
|
deleteMessage(message) {
|
|
379
485
|
return __awaiter(this, void 0, void 0, function* () {
|
|
380
486
|
yield this.chatClientService.chatClient.deleteMessage(message.id);
|
|
381
487
|
});
|
|
382
488
|
}
|
|
489
|
+
/**
|
|
490
|
+
* Uploads files to the channel. If you want to know more about [file uploads](https://getstream.io/chat/docs/javascript/file_uploads/?language=javascript) check out the platform documentation.
|
|
491
|
+
* @param uploads the attachments to upload (output of the [`AttachmentService`](./AttachmentService.mdx))
|
|
492
|
+
* @returns the result of file upload requests
|
|
493
|
+
*/
|
|
383
494
|
uploadAttachments(uploads) {
|
|
384
495
|
return __awaiter(this, void 0, void 0, function* () {
|
|
385
496
|
const result = [];
|
|
@@ -405,6 +516,10 @@ class ChannelService {
|
|
|
405
516
|
return result;
|
|
406
517
|
});
|
|
407
518
|
}
|
|
519
|
+
/**
|
|
520
|
+
* Deletes an uploaded file by URL. If you want to know more about [file uploads](https://getstream.io/chat/docs/javascript/file_uploads/?language=javascript) check out the platform documentation
|
|
521
|
+
* @param attachmentUpload Attachment to be deleted (output of the [`AttachmentService`](./AttachmentService.mdx))
|
|
522
|
+
*/
|
|
408
523
|
deleteAttachment(attachmentUpload) {
|
|
409
524
|
return __awaiter(this, void 0, void 0, function* () {
|
|
410
525
|
const channel = this.activeChannelSubject.getValue();
|
|
@@ -413,6 +528,11 @@ class ChannelService {
|
|
|
413
528
|
: channel.deleteFile(attachmentUpload.url));
|
|
414
529
|
});
|
|
415
530
|
}
|
|
531
|
+
/**
|
|
532
|
+
* Returns the autocomplete options for current channel members. If the channel has less than 100 members, it returns the channel members, otherwise sends a [search request](https://getstream.io/chat/docs/javascript/query_members/?language=javascript#pagination-and-ordering) with the given search term.
|
|
533
|
+
* @param searchTerm Text to search for in the names of members
|
|
534
|
+
* @returns The list of members matching the search filter
|
|
535
|
+
*/
|
|
416
536
|
autocompleteMembers(searchTerm) {
|
|
417
537
|
return __awaiter(this, void 0, void 0, function* () {
|
|
418
538
|
const activeChannel = this.activeChannelSubject.getValue();
|
|
@@ -434,6 +554,11 @@ class ChannelService {
|
|
|
434
554
|
}
|
|
435
555
|
});
|
|
436
556
|
}
|
|
557
|
+
/**
|
|
558
|
+
* [Runs a message action](https://getstream.io/chat/docs/rest/#messages-runmessageaction) in the current channel. Updates the message list based on the action result (if no message is returned, the message will be removed from the message list).
|
|
559
|
+
* @param messageId
|
|
560
|
+
* @param formData
|
|
561
|
+
*/
|
|
437
562
|
sendAction(messageId, formData) {
|
|
438
563
|
return __awaiter(this, void 0, void 0, function* () {
|
|
439
564
|
const channel = this.activeChannelSubject.getValue();
|
|
@@ -462,6 +587,10 @@ class ChannelService {
|
|
|
462
587
|
}
|
|
463
588
|
});
|
|
464
589
|
}
|
|
590
|
+
/**
|
|
591
|
+
* Selects or deselects the current message to quote reply to
|
|
592
|
+
* @param message The message to select, if called with `undefined`, it deselects the message
|
|
593
|
+
*/
|
|
465
594
|
selectMessageToQuote(message) {
|
|
466
595
|
this.messageToQuoteSubject.next(message);
|
|
467
596
|
}
|
|
@@ -615,6 +744,28 @@ class ChannelService {
|
|
|
615
744
|
this.activeChannelMessagesSubject.next(this.activeChannelMessagesSubject.getValue());
|
|
616
745
|
});
|
|
617
746
|
}));
|
|
747
|
+
this.activeChannelSubscriptions.push(channel.on('typing.start', (e) => this.ngZone.run(() => this.handleTypingStartEvent(e))));
|
|
748
|
+
this.activeChannelSubscriptions.push(channel.on('typing.stop', (e) => this.ngZone.run(() => this.handleTypingStopEvent(e))));
|
|
749
|
+
}
|
|
750
|
+
/**
|
|
751
|
+
* Call this method if user started typing in the active channel
|
|
752
|
+
* @param parentId The id of the parent message, if user is typing in a thread
|
|
753
|
+
*/
|
|
754
|
+
typingStarted(parentId) {
|
|
755
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
756
|
+
const activeChannel = this.activeChannelSubject.getValue();
|
|
757
|
+
yield (activeChannel === null || activeChannel === void 0 ? void 0 : activeChannel.keystroke(parentId));
|
|
758
|
+
});
|
|
759
|
+
}
|
|
760
|
+
/**
|
|
761
|
+
* Call this method if user stopped typing in the active channel
|
|
762
|
+
* @param parentId The id of the parent message, if user were typing in a thread
|
|
763
|
+
*/
|
|
764
|
+
typingStopped(parentId) {
|
|
765
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
766
|
+
const activeChannel = this.activeChannelSubject.getValue();
|
|
767
|
+
yield (activeChannel === null || activeChannel === void 0 ? void 0 : activeChannel.stopTyping(parentId));
|
|
768
|
+
});
|
|
618
769
|
}
|
|
619
770
|
messageUpdated(event) {
|
|
620
771
|
this.ngZone.run(() => {
|
|
@@ -837,6 +988,41 @@ class ChannelService {
|
|
|
837
988
|
return Object.assign(Object.assign({}, formatMessage), { readBy: isThreadMessage ? [] : getReadBy(formatMessage, channel) });
|
|
838
989
|
}
|
|
839
990
|
}
|
|
991
|
+
handleTypingStartEvent(event) {
|
|
992
|
+
var _a, _b;
|
|
993
|
+
if (((_a = event.user) === null || _a === void 0 ? void 0 : _a.id) === ((_b = this.chatClientService.chatClient.user) === null || _b === void 0 ? void 0 : _b.id)) {
|
|
994
|
+
return;
|
|
995
|
+
}
|
|
996
|
+
const isTypingInThread = !!event.parent_id;
|
|
997
|
+
if (isTypingInThread &&
|
|
998
|
+
event.parent_id !== this.activeParentMessageIdSubject.getValue()) {
|
|
999
|
+
return;
|
|
1000
|
+
}
|
|
1001
|
+
const subject = isTypingInThread
|
|
1002
|
+
? this.usersTypingInThreadSubject
|
|
1003
|
+
: this.usersTypingInChannelSubject;
|
|
1004
|
+
const users = subject.getValue();
|
|
1005
|
+
const user = event.user;
|
|
1006
|
+
if (user && !users.find((u) => u.id === user.id)) {
|
|
1007
|
+
users.push(user);
|
|
1008
|
+
subject.next([...users]);
|
|
1009
|
+
}
|
|
1010
|
+
}
|
|
1011
|
+
handleTypingStopEvent(event) {
|
|
1012
|
+
const usersTypingInChannel = this.usersTypingInChannelSubject.getValue();
|
|
1013
|
+
const usersTypingInThread = this.usersTypingInThreadSubject.getValue();
|
|
1014
|
+
const user = event.user;
|
|
1015
|
+
if (user && usersTypingInChannel.find((u) => u.id === user.id)) {
|
|
1016
|
+
usersTypingInChannel.splice(usersTypingInChannel.findIndex((u) => u.id === user.id), 1);
|
|
1017
|
+
this.usersTypingInChannelSubject.next([...usersTypingInChannel]);
|
|
1018
|
+
return;
|
|
1019
|
+
}
|
|
1020
|
+
if (user && usersTypingInThread.find((u) => u.id === user.id)) {
|
|
1021
|
+
usersTypingInThread.splice(usersTypingInThread.findIndex((u) => u.id === user.id), 1);
|
|
1022
|
+
this.usersTypingInThreadSubject.next([...usersTypingInThread]);
|
|
1023
|
+
return;
|
|
1024
|
+
}
|
|
1025
|
+
}
|
|
840
1026
|
}
|
|
841
1027
|
ChannelService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: ChannelService, deps: [{ token: ChatClientService }, { token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
842
1028
|
ChannelService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: ChannelService, providedIn: 'root' });
|
|
@@ -847,8 +1033,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImpor
|
|
|
847
1033
|
}]
|
|
848
1034
|
}], ctorParameters: function () { return [{ type: ChatClientService }, { type: i0.NgZone }]; } });
|
|
849
1035
|
|
|
1036
|
+
/**
|
|
1037
|
+
* The `ThemeService` can be used to change the theme of the chat UI and to customize the theme. Our [themeing guide](../concepts/themeing-and-css.mdx) gives a complete overview about the topic.
|
|
1038
|
+
*/
|
|
850
1039
|
class ThemeService {
|
|
851
1040
|
constructor() {
|
|
1041
|
+
/**
|
|
1042
|
+
* A Subject that can be used to get or set the currently active theme.
|
|
1043
|
+
*/
|
|
852
1044
|
this.theme$ = new BehaviorSubject('light');
|
|
853
1045
|
this.defaultDarkModeVariables = {
|
|
854
1046
|
'--bg-gradient-end': '#101214',
|
|
@@ -889,9 +1081,17 @@ class ThemeService {
|
|
|
889
1081
|
}
|
|
890
1082
|
});
|
|
891
1083
|
}
|
|
1084
|
+
/**
|
|
1085
|
+
* A getter that returns the currently set custom light theme variables.
|
|
1086
|
+
* @returns An object where the keys are theme variables, and the values are the currently set CSS values.
|
|
1087
|
+
*/
|
|
892
1088
|
get customLightThemeVariables() {
|
|
893
1089
|
return this._customLightThemeVariables;
|
|
894
1090
|
}
|
|
1091
|
+
/**
|
|
1092
|
+
* A setter that can be used to overwrite the values of the CSS theme variables of the light theme.
|
|
1093
|
+
* @param variables An object where the keys are theme variables, and the values are CSS values.
|
|
1094
|
+
*/
|
|
895
1095
|
set customLightThemeVariables(variables) {
|
|
896
1096
|
const prevVariables = this.customLightThemeVariables;
|
|
897
1097
|
if (prevVariables) {
|
|
@@ -902,9 +1102,17 @@ class ThemeService {
|
|
|
902
1102
|
this.theme$.next('light');
|
|
903
1103
|
}
|
|
904
1104
|
}
|
|
1105
|
+
/**
|
|
1106
|
+
* A getter that returns the currently set custom dark theme variables.
|
|
1107
|
+
* @returns An object where the keys are theme variables, and the values are the currently set CSS values.
|
|
1108
|
+
*/
|
|
905
1109
|
get customDarkThemeVariables() {
|
|
906
1110
|
return this._customDarkThemeVariables;
|
|
907
1111
|
}
|
|
1112
|
+
/**
|
|
1113
|
+
* A setter that can be used to overwrite the values of the CSS theme variables of the dark theme.
|
|
1114
|
+
* @param variables An object where the keys are theme variables, and the values are CSS values.
|
|
1115
|
+
*/
|
|
908
1116
|
set customDarkThemeVariables(variables) {
|
|
909
1117
|
const prevVariables = this.customDarkThemeVariables;
|
|
910
1118
|
if (prevVariables) {
|
|
@@ -948,6 +1156,9 @@ const isImageAttachment = (attachment) => {
|
|
|
948
1156
|
!attachment.og_scrape_url);
|
|
949
1157
|
};
|
|
950
1158
|
|
|
1159
|
+
/**
|
|
1160
|
+
* The `AttachmentService` manages the uploads of a message input.
|
|
1161
|
+
*/
|
|
951
1162
|
class AttachmentService {
|
|
952
1163
|
constructor(channelService, notificationService) {
|
|
953
1164
|
this.channelService = channelService;
|
|
@@ -958,9 +1169,17 @@ class AttachmentService {
|
|
|
958
1169
|
this.attachmentUploadInProgressCounterSubject.asObservable();
|
|
959
1170
|
this.attachmentUploads$ = this.attachmentUploadsSubject.asObservable();
|
|
960
1171
|
}
|
|
1172
|
+
/**
|
|
1173
|
+
* Resets the attachments uploads (for example after the message with the attachments sent successfully)
|
|
1174
|
+
*/
|
|
961
1175
|
resetAttachmentUploads() {
|
|
962
1176
|
this.attachmentUploadsSubject.next([]);
|
|
963
1177
|
}
|
|
1178
|
+
/**
|
|
1179
|
+
* Uploads the selected files, and creates preview for image files. The result is propagated throught the `attachmentUploads$` stream.
|
|
1180
|
+
* @param fileList The files selected by the user
|
|
1181
|
+
* @returns A promise with the result
|
|
1182
|
+
*/
|
|
964
1183
|
filesSelected(fileList) {
|
|
965
1184
|
return __awaiter(this, void 0, void 0, function* () {
|
|
966
1185
|
if (!fileList) {
|
|
@@ -996,6 +1215,11 @@ class AttachmentService {
|
|
|
996
1215
|
yield this.uploadAttachments(newUploads);
|
|
997
1216
|
});
|
|
998
1217
|
}
|
|
1218
|
+
/**
|
|
1219
|
+
* Retries to upload an attachment.
|
|
1220
|
+
* @param file
|
|
1221
|
+
* @returns A promise with the result
|
|
1222
|
+
*/
|
|
999
1223
|
retryAttachmentUpload(file) {
|
|
1000
1224
|
return __awaiter(this, void 0, void 0, function* () {
|
|
1001
1225
|
const attachmentUploads = this.attachmentUploadsSubject.getValue();
|
|
@@ -1008,6 +1232,10 @@ class AttachmentService {
|
|
|
1008
1232
|
yield this.uploadAttachments([upload]);
|
|
1009
1233
|
});
|
|
1010
1234
|
}
|
|
1235
|
+
/**
|
|
1236
|
+
* Deletes an attachment, the attachment can have any state (`error`, `uploading` or `success`).
|
|
1237
|
+
* @param upload
|
|
1238
|
+
*/
|
|
1011
1239
|
deleteAttachment(upload) {
|
|
1012
1240
|
return __awaiter(this, void 0, void 0, function* () {
|
|
1013
1241
|
const attachmentUploads = this.attachmentUploadsSubject.getValue();
|
|
@@ -1026,6 +1254,10 @@ class AttachmentService {
|
|
|
1026
1254
|
this.attachmentUploadsSubject.next([...attachmentUploads]);
|
|
1027
1255
|
});
|
|
1028
1256
|
}
|
|
1257
|
+
/**
|
|
1258
|
+
* Maps the current uploads to a format that can be sent along with the message to the Stream API.
|
|
1259
|
+
* @returns the attachments
|
|
1260
|
+
*/
|
|
1029
1261
|
mapToAttachments() {
|
|
1030
1262
|
const attachmentUploads = this.attachmentUploadsSubject.getValue();
|
|
1031
1263
|
return attachmentUploads
|
|
@@ -1047,6 +1279,10 @@ class AttachmentService {
|
|
|
1047
1279
|
return attachment;
|
|
1048
1280
|
});
|
|
1049
1281
|
}
|
|
1282
|
+
/**
|
|
1283
|
+
* Maps attachments received from the Stream API to uploads. This is useful when editing a message.
|
|
1284
|
+
* @param attachments Attachemnts received with the message
|
|
1285
|
+
*/
|
|
1050
1286
|
createFromAttachments(attachments) {
|
|
1051
1287
|
const attachmentUploads = [];
|
|
1052
1288
|
attachments.forEach((attachment) => {
|
|
@@ -1217,10 +1453,18 @@ const en = {
|
|
|
1217
1453
|
},
|
|
1218
1454
|
};
|
|
1219
1455
|
|
|
1456
|
+
/**
|
|
1457
|
+
* The `StreamI18nService` can be used to customize the labels of the chat UI. Our [translation guide](../concepts/translation.mdx) covers this topic in detail.
|
|
1458
|
+
*/
|
|
1220
1459
|
class StreamI18nService {
|
|
1221
1460
|
constructor(translteService) {
|
|
1222
1461
|
this.translteService = translteService;
|
|
1223
1462
|
}
|
|
1463
|
+
/**
|
|
1464
|
+
* Registers the translation to the [ngx-translate](https://github.com/ngx-translate/core) TranslateService.
|
|
1465
|
+
* @param lang The language key to register the translation to
|
|
1466
|
+
* @param overrides An object which keys are translation keys, and the values are custom translations
|
|
1467
|
+
*/
|
|
1224
1468
|
setTranslation(lang = 'en', overrides) {
|
|
1225
1469
|
if (!this.translteService.defaultLang) {
|
|
1226
1470
|
this.translteService.defaultLang = lang;
|
|
@@ -1228,14 +1472,14 @@ class StreamI18nService {
|
|
|
1228
1472
|
this.translteService.setTranslation(lang, { streamChat: Object.assign(Object.assign({}, en.streamChat), overrides) }, true);
|
|
1229
1473
|
}
|
|
1230
1474
|
}
|
|
1231
|
-
StreamI18nService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: StreamI18nService, deps: [{ token:
|
|
1475
|
+
StreamI18nService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: StreamI18nService, deps: [{ token: i2.TranslateService }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
1232
1476
|
StreamI18nService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: StreamI18nService, providedIn: 'root' });
|
|
1233
1477
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: StreamI18nService, decorators: [{
|
|
1234
1478
|
type: Injectable,
|
|
1235
1479
|
args: [{
|
|
1236
1480
|
providedIn: 'root',
|
|
1237
1481
|
}]
|
|
1238
|
-
}], ctorParameters: function () { return [{ type:
|
|
1482
|
+
}], ctorParameters: function () { return [{ type: i2.TranslateService }]; } });
|
|
1239
1483
|
|
|
1240
1484
|
class AvatarComponent {
|
|
1241
1485
|
constructor() {
|
|
@@ -1269,7 +1513,7 @@ class IconComponent {
|
|
|
1269
1513
|
constructor() { }
|
|
1270
1514
|
}
|
|
1271
1515
|
IconComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: IconComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1272
|
-
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", directives: [{ type: i6.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type:
|
|
1516
|
+
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", directives: [{ type: i6.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i2.TranslateDirective, selector: "[translate],[ngx-translate]", inputs: ["translate", "translateParams"] }] });
|
|
1273
1517
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: IconComponent, decorators: [{
|
|
1274
1518
|
type: Component,
|
|
1275
1519
|
args: [{
|
|
@@ -1390,11 +1634,46 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImpor
|
|
|
1390
1634
|
type: Output
|
|
1391
1635
|
}] } });
|
|
1392
1636
|
|
|
1637
|
+
/**
|
|
1638
|
+
* If you have an emoji picker in your application, you can propagate the selected emoji to the textarea using this service, more info can be found in [custom emoji picker guide](../code-examples/emoji-picker.mdx)
|
|
1639
|
+
*/
|
|
1640
|
+
class EmojiInputService {
|
|
1641
|
+
constructor() {
|
|
1642
|
+
/**
|
|
1643
|
+
* If you have an emoji picker in your application, you can propagate the selected emoji to the textarea using this Subject, more info can be found in [custom emoji picker guide](../code-examples/emoji-picker.mdx)
|
|
1644
|
+
*/
|
|
1645
|
+
this.emojiInput$ = new Subject();
|
|
1646
|
+
}
|
|
1647
|
+
}
|
|
1648
|
+
EmojiInputService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: EmojiInputService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
1649
|
+
EmojiInputService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: EmojiInputService, providedIn: 'root' });
|
|
1650
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: EmojiInputService, decorators: [{
|
|
1651
|
+
type: Injectable,
|
|
1652
|
+
args: [{
|
|
1653
|
+
providedIn: 'root',
|
|
1654
|
+
}]
|
|
1655
|
+
}], ctorParameters: function () { return []; } });
|
|
1656
|
+
|
|
1657
|
+
/**
|
|
1658
|
+
* The `MessageInputConfigService` is used to keep a consistent configuration among the different [`MessageInput`](../components/message-input.mdx) components if your UI has more than one input component.
|
|
1659
|
+
*/
|
|
1393
1660
|
class MessageInputConfigService {
|
|
1394
1661
|
constructor() {
|
|
1662
|
+
/**
|
|
1663
|
+
* If file upload is enabled, the user can open a file selector from the input. Please note that the user also needs to have the necessary [channel capability](https://getstream.io/chat/docs/javascript/channel_capabilities/?language=javascript).
|
|
1664
|
+
*/
|
|
1395
1665
|
this.isFileUploadEnabled = true;
|
|
1666
|
+
/**
|
|
1667
|
+
* If true, users can mention other users in messages. You also [need to use the `AutocompleteTextarea`](../concepts/opt-in-architecture.mdx) for this feature to work.
|
|
1668
|
+
*/
|
|
1396
1669
|
this.areMentionsEnabled = true;
|
|
1670
|
+
/**
|
|
1671
|
+
* If `false`, users can only upload one attachment per message
|
|
1672
|
+
*/
|
|
1397
1673
|
this.isMultipleFileUploadEnabled = true;
|
|
1674
|
+
/**
|
|
1675
|
+
* The scope for user mentions, either members of the current channel of members of the application
|
|
1676
|
+
*/
|
|
1398
1677
|
this.mentionScope = 'channel';
|
|
1399
1678
|
}
|
|
1400
1679
|
}
|
|
@@ -1407,8 +1686,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImpor
|
|
|
1407
1686
|
}]
|
|
1408
1687
|
}], ctorParameters: function () { return []; } });
|
|
1409
1688
|
|
|
1689
|
+
/**
|
|
1690
|
+
* The `ImageLoadService` is used to position the scrollbar in the message list
|
|
1691
|
+
*/
|
|
1410
1692
|
class ImageLoadService {
|
|
1411
1693
|
constructor() {
|
|
1694
|
+
/**
|
|
1695
|
+
* A subject that can be used to notify the message list if an image attachment finished loading
|
|
1696
|
+
*/
|
|
1412
1697
|
this.imageLoad$ = new Subject();
|
|
1413
1698
|
}
|
|
1414
1699
|
}
|
|
@@ -1511,7 +1796,7 @@ class AttachmentPreviewListComponent {
|
|
|
1511
1796
|
}
|
|
1512
1797
|
}
|
|
1513
1798
|
AttachmentPreviewListComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: AttachmentPreviewListComponent, deps: [{ token: AttachmentService }], target: i0.ɵɵFactoryTarget.Component });
|
|
1514
|
-
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)=\"retryAttachmentUpload(attachmentUpload.file)\"\n (keyup.enter)=\"retryAttachmentUpload(attachmentUpload.file)\"\n data-testclass=\"upload-error\"\n >\n <stream-icon icon=\"retry\"></stream-icon>\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)=\"deleteAttachment(attachmentUpload)\"\n (keyup.enter)=\"deleteAttachment(attachmentUpload)\"\n >\n <stream-icon icon=\"close\"></stream-icon>\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\n data-testclass=\"loading-indicator\"\n color=\"rgba(255,255,255,0.7)\"\n *ngIf=\"attachmentUpload.state === 'uploading'\"\n ></stream-loading-indicator>\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 icon=\"file\"></stream-icon>\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)=\"retryAttachmentUpload(attachmentUpload.file)\"\n (keyup.enter)=\"retryAttachmentUpload(attachmentUpload.file)\"\n translate\n >\n streamChat.failed\n </div>\n <div\n class=\"rfu-file-previewer__retry\"\n (click)=\"retryAttachmentUpload(attachmentUpload.file)\"\n (keyup.enter)=\"retryAttachmentUpload(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)=\"deleteAttachment(attachmentUpload)\"\n (keyup.enter)=\"deleteAttachment(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></stream-loading-indicator>\n </div>\n </li>\n </ol>\n </div>\n </ng-container>\n</div>\n", components: [{ type: IconComponent, selector: "stream-icon", inputs: ["icon", "size"] }, { type: LoadingIndicatorComponent, selector: "stream-loading-indicator", inputs: ["size", "color"] }], directives: [{ type: i6.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i6.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type:
|
|
1799
|
+
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)=\"retryAttachmentUpload(attachmentUpload.file)\"\n (keyup.enter)=\"retryAttachmentUpload(attachmentUpload.file)\"\n data-testclass=\"upload-error\"\n >\n <stream-icon icon=\"retry\"></stream-icon>\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)=\"deleteAttachment(attachmentUpload)\"\n (keyup.enter)=\"deleteAttachment(attachmentUpload)\"\n >\n <stream-icon icon=\"close\"></stream-icon>\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\n data-testclass=\"loading-indicator\"\n color=\"rgba(255,255,255,0.7)\"\n *ngIf=\"attachmentUpload.state === 'uploading'\"\n ></stream-loading-indicator>\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 icon=\"file\"></stream-icon>\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)=\"retryAttachmentUpload(attachmentUpload.file)\"\n (keyup.enter)=\"retryAttachmentUpload(attachmentUpload.file)\"\n translate\n >\n streamChat.failed\n </div>\n <div\n class=\"rfu-file-previewer__retry\"\n (click)=\"retryAttachmentUpload(attachmentUpload.file)\"\n (keyup.enter)=\"retryAttachmentUpload(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)=\"deleteAttachment(attachmentUpload)\"\n (keyup.enter)=\"deleteAttachment(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></stream-loading-indicator>\n </div>\n </li>\n </ol>\n </div>\n </ng-container>\n</div>\n", components: [{ type: IconComponent, selector: "stream-icon", inputs: ["icon", "size"] }, { type: LoadingIndicatorComponent, selector: "stream-loading-indicator", inputs: ["size", "color"] }], directives: [{ type: i6.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i6.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i2.TranslateDirective, selector: "[translate],[ngx-translate]", inputs: ["translate", "translateParams"] }], pipes: { "async": i6.AsyncPipe } });
|
|
1515
1800
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: AttachmentPreviewListComponent, decorators: [{
|
|
1516
1801
|
type: Component,
|
|
1517
1802
|
args: [{
|
|
@@ -1522,7 +1807,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImpor
|
|
|
1522
1807
|
}], ctorParameters: function () { return [{ type: AttachmentService }]; } });
|
|
1523
1808
|
|
|
1524
1809
|
class MessageInputComponent {
|
|
1525
|
-
constructor(channelService, notificationService, attachmentService, configService, textareaType, componentFactoryResolver, cdRef, chatClient) {
|
|
1810
|
+
constructor(channelService, notificationService, attachmentService, configService, textareaType, componentFactoryResolver, cdRef, chatClient, emojiInputService) {
|
|
1526
1811
|
this.channelService = channelService;
|
|
1527
1812
|
this.notificationService = notificationService;
|
|
1528
1813
|
this.attachmentService = attachmentService;
|
|
@@ -1531,10 +1816,12 @@ class MessageInputComponent {
|
|
|
1531
1816
|
this.componentFactoryResolver = componentFactoryResolver;
|
|
1532
1817
|
this.cdRef = cdRef;
|
|
1533
1818
|
this.chatClient = chatClient;
|
|
1819
|
+
this.emojiInputService = emojiInputService;
|
|
1534
1820
|
this.mode = 'main';
|
|
1535
1821
|
this.messageUpdate = new EventEmitter();
|
|
1536
1822
|
this.textareaValue = '';
|
|
1537
1823
|
this.mentionedUsers = [];
|
|
1824
|
+
this.typingStart$ = new Subject();
|
|
1538
1825
|
this.subscriptions = [];
|
|
1539
1826
|
this.isViewInited = false;
|
|
1540
1827
|
this.subscriptions.push(this.attachmentService.attachmentUploadInProgressCounter$.subscribe((counter) => {
|
|
@@ -1576,6 +1863,8 @@ class MessageInputComponent {
|
|
|
1576
1863
|
this.mentionScope = this.configService.mentionScope;
|
|
1577
1864
|
this.commandAutocompleteItemTemplate =
|
|
1578
1865
|
this.configService.commandAutocompleteItemTemplate;
|
|
1866
|
+
this.emojiPickerTemplate = this.configService.emojiPickerTemplate;
|
|
1867
|
+
this.subscriptions.push(this.typingStart$.subscribe(() => void this.channelService.typingStarted(this.parentMessageId)));
|
|
1579
1868
|
}
|
|
1580
1869
|
ngAfterViewInit() {
|
|
1581
1870
|
this.isViewInited = true;
|
|
@@ -1613,6 +1902,9 @@ class MessageInputComponent {
|
|
|
1613
1902
|
if (changes.mentionScope) {
|
|
1614
1903
|
this.configService.mentionScope = this.mentionScope;
|
|
1615
1904
|
}
|
|
1905
|
+
if (changes.emojiPickerTemplate) {
|
|
1906
|
+
this.configService.emojiPickerTemplate = this.emojiPickerTemplate;
|
|
1907
|
+
}
|
|
1616
1908
|
if (changes.mode) {
|
|
1617
1909
|
this.setCanSendMessages();
|
|
1618
1910
|
}
|
|
@@ -1646,16 +1938,10 @@ class MessageInputComponent {
|
|
|
1646
1938
|
if (!this.isUpdate) {
|
|
1647
1939
|
this.textareaValue = '';
|
|
1648
1940
|
}
|
|
1649
|
-
let parentMessageId = undefined;
|
|
1650
|
-
if (this.mode === 'thread') {
|
|
1651
|
-
this.channelService.activeParentMessageId$
|
|
1652
|
-
.pipe(first())
|
|
1653
|
-
.subscribe((id) => (parentMessageId = id));
|
|
1654
|
-
}
|
|
1655
1941
|
try {
|
|
1656
1942
|
yield (this.isUpdate
|
|
1657
1943
|
? this.channelService.updateMessage(Object.assign(Object.assign({}, this.message), { text: text, attachments: attachments }))
|
|
1658
|
-
: this.channelService.sendMessage(text, attachments, this.mentionedUsers, parentMessageId, (_a = this.quotedMessage) === null || _a === void 0 ? void 0 : _a.id));
|
|
1944
|
+
: this.channelService.sendMessage(text, attachments, this.mentionedUsers, this.parentMessageId, (_a = this.quotedMessage) === null || _a === void 0 ? void 0 : _a.id));
|
|
1659
1945
|
this.messageUpdate.emit();
|
|
1660
1946
|
if (!this.isUpdate) {
|
|
1661
1947
|
this.attachmentService.resetAttachmentUploads();
|
|
@@ -1666,6 +1952,7 @@ class MessageInputComponent {
|
|
|
1666
1952
|
this.notificationService.addTemporaryNotification('streamChat.Edit message request failed');
|
|
1667
1953
|
}
|
|
1668
1954
|
}
|
|
1955
|
+
void this.channelService.typingStopped(this.parentMessageId);
|
|
1669
1956
|
if (this.quotedMessage) {
|
|
1670
1957
|
this.deselectMessageToQuote();
|
|
1671
1958
|
}
|
|
@@ -1777,21 +2064,30 @@ class MessageInputComponent {
|
|
|
1777
2064
|
this.initTextarea();
|
|
1778
2065
|
}
|
|
1779
2066
|
}
|
|
2067
|
+
get parentMessageId() {
|
|
2068
|
+
let parentMessageId = undefined;
|
|
2069
|
+
if (this.mode === 'thread') {
|
|
2070
|
+
this.channelService.activeParentMessageId$
|
|
2071
|
+
.pipe(first())
|
|
2072
|
+
.subscribe((id) => (parentMessageId = id));
|
|
2073
|
+
}
|
|
2074
|
+
return parentMessageId;
|
|
2075
|
+
}
|
|
1780
2076
|
}
|
|
1781
|
-
MessageInputComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: MessageInputComponent, deps: [{ token: ChannelService }, { token: NotificationService }, { token: AttachmentService }, { token: MessageInputConfigService }, { token: textareaInjectionToken }, { token: i0.ComponentFactoryResolver }, { token: i0.ChangeDetectorRef }, { token: ChatClientService }], target: i0.ɵɵFactoryTarget.Component });
|
|
1782
|
-
MessageInputComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.5", type: MessageInputComponent, selector: "stream-message-input", inputs: { isFileUploadEnabled: "isFileUploadEnabled", areMentionsEnabled: "areMentionsEnabled", mentionScope: "mentionScope", mentionAutocompleteItemTemplate: "mentionAutocompleteItemTemplate", commandAutocompleteItemTemplate: "commandAutocompleteItemTemplate", mode: "mode", acceptedFileTypes: "acceptedFileTypes", isMultipleFileUploadEnabled: "isMultipleFileUploadEnabled", message: "message" }, outputs: { messageUpdate: "messageUpdate" }, providers: [AttachmentService], viewQueries: [{ propertyName: "fileInput", first: true, predicate: ["fileInput"], descendants: true }, { propertyName: "textareaAnchor", first: true, predicate: TextareaDirective, descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div\n class=\"{{\n mode === 'main' ? 'str-chat__input-flat' : 'str-chat__small-message-input'\n }}\"\n [class.str-chat__input-flat-has-attachments]=\"\n (attachmentUploads$ | async)!.length > 0\n \"\n [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\n icon=\"close-no-outline\"\n style=\"font-size: 10px; line-height: 10px\"\n ></stream-icon>\n </button>\n </div>\n <div class=\"quoted-message-preview-content\">\n <stream-avatar\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>\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 <stream-attachment-preview-list\n class=\"rfu-image-previewer-angular-host\"\n ></stream-attachment-preview-list>\n <div class=\"rta str-chat__textarea\">\n <ng-template\n *ngIf=\"canSendMessages; else notAllowed\"\n streamTextarea\n [(value)]=\"textareaValue\"\n (send)=\"messageSent()\"\n [componentRef]=\"textareaRef\"\n (userMentions)=\"mentionedUsers = $event\"\n [areMentionsEnabled]=\"areMentionsEnabled\"\n [mentionAutocompleteItemTemplate]=\"mentionAutocompleteItemTemplate\"\n [commandAutocompleteItemTemplate]=\"commandAutocompleteItemTemplate\"\n [mentionScope]=\"mentionScope\"\n ></ng-template>\n <ng-template #notAllowed>\n <textarea\n disabled\n rows=\"1\"\n [value]=\"\n (mode === 'thread'\n ? 'You can\\'t send thread replies in this channel'\n : 'streamChat.You can\\'t send messages in this channel'\n ) | translate\n \"\n class=\"rta__textarea str-chat__textarea__textarea\"\n ></textarea>\n </ng-template>\n </div>\n <div\n *ngIf=\"isFileUploadEnabled && isFileUploadAuthorized && canSendMessages\"\n class=\"str-chat__fileupload-wrapper\"\n data-testid=\"file-upload-button\"\n >\n <div class=\"str-chat__tooltip\">\n {{ \"streamChat.Attach files\" | translate }}\n </div>\n <div class=\"rfu-file-upload-button\">\n <label>\n <input\n #fileInput\n type=\"file\"\n class=\"rfu-file-input\"\n data-testid=\"file-input\"\n [accept]=\"accept\"\n [multiple]=\"isMultipleFileUploadEnabled\"\n (change)=\"filesSelected(fileInput.files)\"\n />\n <span class=\"str-chat__input-flat-fileupload\">\n <stream-icon icon=\"file-upload\"></stream-icon>\n </span>\n </label>\n </div>\n </div>\n </div>\n <button\n *ngIf=\"canSendMessages\"\n data-testid=\"send-button\"\n class=\"str-chat__send-button\"\n (click)=\"messageSent()\"\n (keyup.enter)=\"messageSent()\"\n >\n <stream-icon icon=\"send\"></stream-icon>\n </button>\n </div>\n</div>\n", components: [{ type: IconComponent, selector: "stream-icon", inputs: ["icon", "size"] }, { type: AvatarComponent, selector: "stream-avatar", inputs: ["name", "imageUrl", "size"] }, { type: AttachmentListComponent, selector: "stream-attachment-list", inputs: ["messageId", "attachments"] }, { type: AttachmentPreviewListComponent, selector: "stream-attachment-preview-list" }], directives: [{ type: i6.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: TextareaDirective, selector: "[streamTextarea]", inputs: ["componentRef", "areMentionsEnabled", "mentionAutocompleteItemTemplate", "mentionScope", "commandAutocompleteItemTemplate", "value"], outputs: ["valueChange", "send", "userMentions"] }], pipes: { "async": i6.AsyncPipe, "translate":
|
|
2077
|
+
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 });
|
|
2078
|
+
MessageInputComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.5", type: MessageInputComponent, selector: "stream-message-input", inputs: { isFileUploadEnabled: "isFileUploadEnabled", areMentionsEnabled: "areMentionsEnabled", mentionScope: "mentionScope", mentionAutocompleteItemTemplate: "mentionAutocompleteItemTemplate", commandAutocompleteItemTemplate: "commandAutocompleteItemTemplate", emojiPickerTemplate: "emojiPickerTemplate", mode: "mode", acceptedFileTypes: "acceptedFileTypes", isMultipleFileUploadEnabled: "isMultipleFileUploadEnabled", message: "message" }, 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\n icon=\"close-no-outline\"\n style=\"font-size: 10px; line-height: 10px\"\n ></stream-icon>\n </button>\n </div>\n <div class=\"quoted-message-preview-content\">\n <stream-avatar\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>\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 <stream-attachment-preview-list\n class=\"rfu-image-previewer-angular-host\"\n ></stream-attachment-preview-list>\n <div class=\"rta str-chat__textarea str-chat-angular__textarea\">\n <ng-container *ngIf=\"emojiPickerTemplate\">\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: { emojiInput$: emojiInputService.emojiInput$ }\n \"\n ></ng-container>\n </div>\n </ng-container>\n <ng-template\n *ngIf=\"canSendMessages; 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 [mentionAutocompleteItemTemplate]=\"mentionAutocompleteItemTemplate\"\n [commandAutocompleteItemTemplate]=\"commandAutocompleteItemTemplate\"\n [mentionScope]=\"mentionScope\"\n ></ng-template>\n <ng-template #notAllowed>\n <textarea\n disabled\n rows=\"1\"\n [value]=\"\n (mode === 'thread'\n ? 'You can\\'t send thread replies in this channel'\n : 'streamChat.You can\\'t send messages in this channel'\n ) | translate\n \"\n class=\"rta__textarea str-chat__textarea__textarea\"\n ></textarea>\n </ng-template>\n </div>\n <div\n *ngIf=\"isFileUploadEnabled && isFileUploadAuthorized && canSendMessages\"\n class=\"str-chat__fileupload-wrapper\"\n data-testid=\"file-upload-button\"\n >\n <div class=\"str-chat__tooltip\">\n {{ \"streamChat.Attach files\" | translate }}\n </div>\n <div class=\"rfu-file-upload-button\">\n <label>\n <input\n #fileInput\n type=\"file\"\n class=\"rfu-file-input\"\n data-testid=\"file-input\"\n [accept]=\"accept\"\n [multiple]=\"isMultipleFileUploadEnabled\"\n (change)=\"filesSelected(fileInput.files)\"\n />\n <span class=\"str-chat__input-flat-fileupload\">\n <stream-icon icon=\"file-upload\"></stream-icon>\n </span>\n </label>\n </div>\n </div>\n </div>\n <button\n *ngIf=\"canSendMessages\"\n data-testid=\"send-button\"\n class=\"str-chat__send-button\"\n (click)=\"messageSent()\"\n (keyup.enter)=\"messageSent()\"\n >\n <stream-icon icon=\"send\"></stream-icon>\n </button>\n </div>\n</div>\n", components: [{ type: IconComponent, selector: "stream-icon", inputs: ["icon", "size"] }, { type: AvatarComponent, selector: "stream-avatar", inputs: ["name", "imageUrl", "size"] }, { type: AttachmentListComponent, selector: "stream-attachment-list", inputs: ["messageId", "attachments"] }, { type: AttachmentPreviewListComponent, selector: "stream-attachment-preview-list" }], directives: [{ type: i6.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i6.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet"] }, { type: TextareaDirective, selector: "[streamTextarea]", inputs: ["componentRef", "areMentionsEnabled", "mentionAutocompleteItemTemplate", "mentionScope", "commandAutocompleteItemTemplate", "value"], outputs: ["valueChange", "send", "userMentions"] }], pipes: { "async": i6.AsyncPipe, "translate": i2.TranslatePipe } });
|
|
1783
2079
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: MessageInputComponent, decorators: [{
|
|
1784
2080
|
type: Component,
|
|
1785
2081
|
args: [{
|
|
1786
2082
|
selector: 'stream-message-input',
|
|
1787
2083
|
templateUrl: './message-input.component.html',
|
|
1788
2084
|
styles: [],
|
|
1789
|
-
providers: [AttachmentService],
|
|
2085
|
+
providers: [AttachmentService, EmojiInputService],
|
|
1790
2086
|
}]
|
|
1791
2087
|
}], ctorParameters: function () { return [{ type: ChannelService }, { type: NotificationService }, { type: AttachmentService }, { type: MessageInputConfigService }, { type: i0.Type, decorators: [{
|
|
1792
2088
|
type: Inject,
|
|
1793
2089
|
args: [textareaInjectionToken]
|
|
1794
|
-
}] }, { type: i0.ComponentFactoryResolver }, { type: i0.ChangeDetectorRef }, { type: ChatClientService }]; }, propDecorators: { isFileUploadEnabled: [{
|
|
2090
|
+
}] }, { type: i0.ComponentFactoryResolver }, { type: i0.ChangeDetectorRef }, { type: ChatClientService }, { type: EmojiInputService }]; }, propDecorators: { isFileUploadEnabled: [{
|
|
1795
2091
|
type: Input
|
|
1796
2092
|
}], areMentionsEnabled: [{
|
|
1797
2093
|
type: Input
|
|
@@ -1801,6 +2097,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImpor
|
|
|
1801
2097
|
type: Input
|
|
1802
2098
|
}], commandAutocompleteItemTemplate: [{
|
|
1803
2099
|
type: Input
|
|
2100
|
+
}], emojiPickerTemplate: [{
|
|
2101
|
+
type: Input
|
|
1804
2102
|
}], mode: [{
|
|
1805
2103
|
type: Input
|
|
1806
2104
|
}], acceptedFileTypes: [{
|
|
@@ -1861,7 +2159,7 @@ class ModalComponent {
|
|
|
1861
2159
|
}
|
|
1862
2160
|
}
|
|
1863
2161
|
ModalComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: ModalComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1864
|
-
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:
|
|
2162
|
+
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"] }] });
|
|
1865
2163
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: ModalComponent, decorators: [{
|
|
1866
2164
|
type: Component,
|
|
1867
2165
|
args: [{
|
|
@@ -1904,7 +2202,7 @@ class NotificationListComponent {
|
|
|
1904
2202
|
}
|
|
1905
2203
|
}
|
|
1906
2204
|
NotificationListComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: NotificationListComponent, deps: [{ token: NotificationService }], target: i0.ɵɵFactoryTarget.Component });
|
|
1907
|
-
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 <stream-notification\n *ngFor=\"let notification of notifications$ | async; trackBy: trackByItem\"\n [type]=\"notification.type\"\n ><div data-testclass=\"notification-content\">\n {{ notification.text | translate: notification.translateParams }}\n </div></stream-notification\n >\n</div>\n", components: [{ type: NotificationComponent, selector: "stream-notification", inputs: ["type"] }], directives: [{ type: i6.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }], pipes: { "async": i6.AsyncPipe, "translate":
|
|
2205
|
+
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 <stream-notification\n *ngFor=\"let notification of notifications$ | async; trackBy: trackByItem\"\n [type]=\"notification.type\"\n ><div data-testclass=\"notification-content\">\n {{ notification.text | translate: notification.translateParams }}\n </div></stream-notification\n >\n</div>\n", components: [{ type: NotificationComponent, selector: "stream-notification", inputs: ["type"] }], directives: [{ type: i6.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }], pipes: { "async": i6.AsyncPipe, "translate": i2.TranslatePipe } });
|
|
1908
2206
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: NotificationListComponent, decorators: [{
|
|
1909
2207
|
type: Component,
|
|
1910
2208
|
args: [{
|
|
@@ -2025,7 +2323,7 @@ class MessageActionsBoxComponent {
|
|
|
2025
2323
|
}
|
|
2026
2324
|
}
|
|
2027
2325
|
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 });
|
|
2028
|
-
MessageActionsBoxComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.5", type: MessageActionsBoxComponent, selector: "stream-message-actions-box", inputs: { messageInputTemplate: "messageInputTemplate", isOpen: "isOpen", isMine: "isMine", message: "message", enabledActions: "enabledActions" }, outputs: { displayedActionsCount: "displayedActionsCount", isEditing: "isEditing" }, viewQueries: [{ propertyName: "messageInput", first: true, predicate: MessageInputComponent, descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div\n data-testid=\"action-box\"\n class=\"str-chat__message-actions-box\"\n [class.str-chat__message-actions-box--open]=\"isOpen\"\n [class.str-chat__message-actions-box--mine]=\"isMine\"\n>\n <ul class=\"str-chat__message-actions-list\">\n <button\n data-testid=\"quote-action\"\n *ngIf=\"isQuoteVisible\"\n (click)=\"quoteClicked()\"\n >\n <li class=\"str-chat__message-actions-list-item\">\n {{ \"streamChat.Reply\" | translate }}\n </li>\n </button>\n <button\n data-testid=\"pin-action\"\n *ngIf=\"isPinVisible\"\n (click)=\"pinClicked()\"\n >\n <li class=\"str-chat__message-actions-list-item\">\n {{\n (message?.pinned ? \"streamChat.Unpin\" : \"streamChat.Pin\") | translate\n }}\n </li>\n </button>\n <button\n data-testid=\"flag-action\"\n *ngIf=\"isFlagVisible\"\n (click)=\"flagClicked()\"\n >\n <li class=\"str-chat__message-actions-list-item\">\n {{ \"streamChat.Flag\" | translate }}\n </li>\n </button>\n <button\n data-testid=\"mute-action\"\n *ngIf=\"isMuteVisible\"\n (click)=\"muteClicked()\"\n >\n <li class=\"str-chat__message-actions-list-item\">\n {{ \"streamChat.Mute\" | translate }}\n </li>\n </button>\n <button\n data-testid=\"edit-action\"\n *ngIf=\"isEditVisible\"\n (click)=\"editClicked()\"\n >\n <li class=\"str-chat__message-actions-list-item\">\n {{ \"streamChat.Edit Message\" | translate }}\n </li>\n </button>\n <button\n data-testid=\"delete-action\"\n *ngIf=\"isDeleteVisible\"\n (click)=\"deleteClicked()\"\n >\n <li class=\"str-chat__message-actions-list-item\">\n {{ \"streamChat.Delete\" | translate }}\n </li>\n </button>\n </ul>\n</div>\n\n<stream-modal\n [isOpen]=\"isEditModalOpen\"\n (isOpenChange)=\"\n isEditModalOpen = $event; isEditModalOpen ? '' : modalClosed()\n \"\n>\n <div class=\"str-chat__edit-message-form\" *ngIf=\"isEditModalOpen\">\n <ng-container *ngIf=\"messageInputTemplate; else defaultInput\">\n <ng-container\n *ngTemplateOutlet=\"\n messageInputTemplate;\n context: {\n message: message,\n messageUpdateHandler: modalClosed\n }\n \"\n ></ng-container>\n </ng-container>\n <ng-template #defaultInput>\n <stream-message-input\n [message]=\"message\"\n (messageUpdate)=\"modalClosed()\"\n ></stream-message-input>\n </ng-template>\n <stream-notification-list></stream-notification-list>\n <div\n class=\"\n str-chat__message-team-form-footer\n str-chat__message-team-form-footer-angular\n \"\n >\n <div class=\"str-chat__edit-message-form-options\">\n <button translate data-testid=\"cancel-button\" (click)=\"modalClosed()\">\n streamChat.Cancel\n </button>\n <button\n type=\"submit\"\n translate\n data-testid=\"send-button\"\n (click)=\"sendClicked()\"\n (keyup.enter)=\"sendClicked()\"\n >\n streamChat.Send\n </button>\n </div>\n </div>\n </div>\n</stream-modal>\n", components: [{ type: ModalComponent, selector: "stream-modal", inputs: ["isOpen"], outputs: ["isOpenChange"] }, { type: MessageInputComponent, selector: "stream-message-input", inputs: ["isFileUploadEnabled", "areMentionsEnabled", "mentionScope", "mentionAutocompleteItemTemplate", "commandAutocompleteItemTemplate", "mode", "acceptedFileTypes", "isMultipleFileUploadEnabled", "message"], outputs: ["messageUpdate"] }, { type: NotificationListComponent, selector: "stream-notification-list" }], directives: [{ type: i6.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i6.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet"] }, { type:
|
|
2326
|
+
MessageActionsBoxComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.5", type: MessageActionsBoxComponent, selector: "stream-message-actions-box", inputs: { messageInputTemplate: "messageInputTemplate", isOpen: "isOpen", isMine: "isMine", message: "message", enabledActions: "enabledActions" }, outputs: { displayedActionsCount: "displayedActionsCount", isEditing: "isEditing" }, viewQueries: [{ propertyName: "messageInput", first: true, predicate: MessageInputComponent, descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div\n data-testid=\"action-box\"\n class=\"str-chat__message-actions-box\"\n [class.str-chat__message-actions-box--open]=\"isOpen\"\n [class.str-chat__message-actions-box--mine]=\"isMine\"\n>\n <ul class=\"str-chat__message-actions-list\">\n <button\n data-testid=\"quote-action\"\n *ngIf=\"isQuoteVisible\"\n (click)=\"quoteClicked()\"\n >\n <li class=\"str-chat__message-actions-list-item\">\n {{ \"streamChat.Reply\" | translate }}\n </li>\n </button>\n <button\n data-testid=\"pin-action\"\n *ngIf=\"isPinVisible\"\n (click)=\"pinClicked()\"\n >\n <li class=\"str-chat__message-actions-list-item\">\n {{\n (message?.pinned ? \"streamChat.Unpin\" : \"streamChat.Pin\") | translate\n }}\n </li>\n </button>\n <button\n data-testid=\"flag-action\"\n *ngIf=\"isFlagVisible\"\n (click)=\"flagClicked()\"\n >\n <li class=\"str-chat__message-actions-list-item\">\n {{ \"streamChat.Flag\" | translate }}\n </li>\n </button>\n <button\n data-testid=\"mute-action\"\n *ngIf=\"isMuteVisible\"\n (click)=\"muteClicked()\"\n >\n <li class=\"str-chat__message-actions-list-item\">\n {{ \"streamChat.Mute\" | translate }}\n </li>\n </button>\n <button\n data-testid=\"edit-action\"\n *ngIf=\"isEditVisible\"\n (click)=\"editClicked()\"\n >\n <li class=\"str-chat__message-actions-list-item\">\n {{ \"streamChat.Edit Message\" | translate }}\n </li>\n </button>\n <button\n data-testid=\"delete-action\"\n *ngIf=\"isDeleteVisible\"\n (click)=\"deleteClicked()\"\n >\n <li class=\"str-chat__message-actions-list-item\">\n {{ \"streamChat.Delete\" | translate }}\n </li>\n </button>\n </ul>\n</div>\n\n<stream-modal\n [isOpen]=\"isEditModalOpen\"\n (isOpenChange)=\"\n isEditModalOpen = $event; isEditModalOpen ? '' : modalClosed()\n \"\n>\n <div class=\"str-chat__edit-message-form\" *ngIf=\"isEditModalOpen\">\n <ng-container *ngIf=\"messageInputTemplate; else defaultInput\">\n <ng-container\n *ngTemplateOutlet=\"\n messageInputTemplate;\n context: {\n message: message,\n messageUpdateHandler: modalClosed\n }\n \"\n ></ng-container>\n </ng-container>\n <ng-template #defaultInput>\n <stream-message-input\n [message]=\"message\"\n (messageUpdate)=\"modalClosed()\"\n ></stream-message-input>\n </ng-template>\n <stream-notification-list></stream-notification-list>\n <div\n class=\"\n str-chat__message-team-form-footer\n str-chat__message-team-form-footer-angular\n \"\n >\n <div class=\"str-chat__edit-message-form-options\">\n <button translate data-testid=\"cancel-button\" (click)=\"modalClosed()\">\n streamChat.Cancel\n </button>\n <button\n type=\"submit\"\n translate\n data-testid=\"send-button\"\n (click)=\"sendClicked()\"\n (keyup.enter)=\"sendClicked()\"\n >\n streamChat.Send\n </button>\n </div>\n </div>\n </div>\n</stream-modal>\n", components: [{ type: ModalComponent, selector: "stream-modal", inputs: ["isOpen"], outputs: ["isOpenChange"] }, { type: MessageInputComponent, selector: "stream-message-input", inputs: ["isFileUploadEnabled", "areMentionsEnabled", "mentionScope", "mentionAutocompleteItemTemplate", "commandAutocompleteItemTemplate", "emojiPickerTemplate", "mode", "acceptedFileTypes", "isMultipleFileUploadEnabled", "message"], outputs: ["messageUpdate"] }, { type: NotificationListComponent, selector: "stream-notification-list" }], directives: [{ type: i6.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i6.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet"] }, { type: i2.TranslateDirective, selector: "[translate],[ngx-translate]", inputs: ["translate", "translateParams"] }], pipes: { "translate": i2.TranslatePipe } });
|
|
2029
2327
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: MessageActionsBoxComponent, decorators: [{
|
|
2030
2328
|
type: Component,
|
|
2031
2329
|
args: [{
|
|
@@ -2081,6 +2379,9 @@ const getDeviceWidth = () => {
|
|
|
2081
2379
|
return { device: 'full', width };
|
|
2082
2380
|
};
|
|
2083
2381
|
|
|
2382
|
+
/**
|
|
2383
|
+
* The `ChannelListToggleService` can be used to toggle the channel list.
|
|
2384
|
+
*/
|
|
2084
2385
|
class ChannelListToggleService {
|
|
2085
2386
|
constructor() {
|
|
2086
2387
|
this.isOpenSubject = new BehaviorSubject(false);
|
|
@@ -2093,18 +2394,34 @@ class ChannelListToggleService {
|
|
|
2093
2394
|
}
|
|
2094
2395
|
});
|
|
2095
2396
|
}
|
|
2397
|
+
/**
|
|
2398
|
+
* Opens the channel list.
|
|
2399
|
+
*/
|
|
2096
2400
|
open() {
|
|
2097
2401
|
this.isOpenSubject.next(true);
|
|
2098
2402
|
}
|
|
2403
|
+
/**
|
|
2404
|
+
* Closes the channel list.
|
|
2405
|
+
*/
|
|
2099
2406
|
close() {
|
|
2100
2407
|
this.isOpenSubject.next(false);
|
|
2101
2408
|
}
|
|
2409
|
+
/**
|
|
2410
|
+
* Opens the channel list if it was closed, and closes if it was opened.
|
|
2411
|
+
*/
|
|
2102
2412
|
toggle() {
|
|
2103
2413
|
this.isOpenSubject.getValue() ? this.close() : this.open();
|
|
2104
2414
|
}
|
|
2415
|
+
/**
|
|
2416
|
+
* Sets the channel list element, on mobile screen size if the user opens the channel list, and clicks outside, the service automatically closes the channel list if a reference to the HTML element is provided.
|
|
2417
|
+
* @param element
|
|
2418
|
+
*/
|
|
2105
2419
|
setMenuElement(element) {
|
|
2106
2420
|
this.menuElement = element;
|
|
2107
2421
|
}
|
|
2422
|
+
/**
|
|
2423
|
+
* This method should be called if a channel was selected, if on mobile, the channel list will be closed.
|
|
2424
|
+
*/
|
|
2108
2425
|
channelSelected() {
|
|
2109
2426
|
if (getDeviceWidth().device === 'mobile') {
|
|
2110
2427
|
this.close();
|
|
@@ -2162,7 +2479,7 @@ class ChannelHeaderComponent {
|
|
|
2162
2479
|
}
|
|
2163
2480
|
}
|
|
2164
2481
|
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 });
|
|
2165
|
-
ChannelHeaderComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.5", type: ChannelHeaderComponent, selector: "stream-channel-header", ngImport: i0, template: "<div class=\"str-chat__header-livestream\">\n <div\n class=\"str-chat__header-hamburger\"\n (click)=\"toggleMenu($event)\"\n (keyup.enter)=\"toggleMenu($event)\"\n >\n <span class=\"str-chat__header-hamburger--line\"></span>\n <span class=\"str-chat__header-hamburger--line\"></span>\n <span class=\"str-chat__header-hamburger--line\"></span>\n </div>\n <stream-avatar\n imageUrl=\"{{ activeChannel?.data?.image }}\"\n name=\"{{ activeChannel?.data?.name }}\"\n ></stream-avatar>\n <div class=\"str-chat__header-livestream-left\">\n <p data-testid=\"name\" class=\"str-chat__header-livestream-left--title\">\n {{ activeChannel?.data?.name }}\n </p>\n <p data-testid=\"info\" class=\"str-chat__header-livestream-left--members\">\n {{'streamChat.{{ memberCount }} members' | translate:memberCountParam}}\n {{canReceiveConnectEvents ? ('streamChat.{{ watcherCount }} online' |\n translate:watcherCountParam) : ''}}\n </p>\n </div>\n</div>\n", components: [{ type: AvatarComponent, selector: "stream-avatar", inputs: ["name", "imageUrl", "size"] }], pipes: { "translate":
|
|
2482
|
+
ChannelHeaderComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.5", type: ChannelHeaderComponent, selector: "stream-channel-header", ngImport: i0, template: "<div class=\"str-chat__header-livestream\">\n <div\n class=\"str-chat__header-hamburger\"\n (click)=\"toggleMenu($event)\"\n (keyup.enter)=\"toggleMenu($event)\"\n >\n <span class=\"str-chat__header-hamburger--line\"></span>\n <span class=\"str-chat__header-hamburger--line\"></span>\n <span class=\"str-chat__header-hamburger--line\"></span>\n </div>\n <stream-avatar\n imageUrl=\"{{ activeChannel?.data?.image }}\"\n name=\"{{ activeChannel?.data?.name }}\"\n ></stream-avatar>\n <div class=\"str-chat__header-livestream-left\">\n <p data-testid=\"name\" class=\"str-chat__header-livestream-left--title\">\n {{ activeChannel?.data?.name }}\n </p>\n <p data-testid=\"info\" class=\"str-chat__header-livestream-left--members\">\n {{'streamChat.{{ memberCount }} members' | translate:memberCountParam}}\n {{canReceiveConnectEvents ? ('streamChat.{{ watcherCount }} online' |\n translate:watcherCountParam) : ''}}\n </p>\n </div>\n</div>\n", components: [{ type: AvatarComponent, selector: "stream-avatar", inputs: ["name", "imageUrl", "size"] }], pipes: { "translate": i2.TranslatePipe } });
|
|
2166
2483
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: ChannelHeaderComponent, decorators: [{
|
|
2167
2484
|
type: Component,
|
|
2168
2485
|
args: [{
|
|
@@ -2247,7 +2564,7 @@ class ChannelPreviewComponent {
|
|
|
2247
2564
|
}
|
|
2248
2565
|
}
|
|
2249
2566
|
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 });
|
|
2250
|
-
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: AvatarComponent, selector: "stream-avatar", inputs: ["name", "imageUrl", "size"] }], pipes: { "translate":
|
|
2567
|
+
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: AvatarComponent, selector: "stream-avatar", inputs: ["name", "imageUrl", "size"] }], pipes: { "translate": i2.TranslatePipe } });
|
|
2251
2568
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: ChannelPreviewComponent, decorators: [{
|
|
2252
2569
|
type: Component,
|
|
2253
2570
|
args: [{
|
|
@@ -2288,7 +2605,7 @@ class ChannelListComponent {
|
|
|
2288
2605
|
}
|
|
2289
2606
|
}
|
|
2290
2607
|
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 });
|
|
2291
|
-
ChannelListComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.5", type: ChannelListComponent, selector: "stream-channel-list", inputs: { customChannelPreviewTemplate: "customChannelPreviewTemplate" }, 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-container\n *ngIf=\"customChannelPreviewTemplate; else defaultTemplate\"\n >\n <div (click)=\"channelSelected()\" (keyup.enter)=\"channelSelected()\">\n <ng-container\n *ngTemplateOutlet=\"\n customChannelPreviewTemplate;\n context: { channel: channel }\n \"\n ></ng-container>\n </div>\n </ng-container>\n <ng-template #defaultTemplate>\n <stream-channel-preview\n data-testclass=\"channel-preview\"\n [channel]=\"channel\"\n (click)=\"channelSelected()\"\n (keyup.enter)=\"channelSelected()\"\n ></stream-channel-preview>\n </ng-template>\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></stream-loading-indicator\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 icon=\"connection-error\"></stream-icon>\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: LoadingIndicatorComponent, selector: "stream-loading-indicator", inputs: ["size", "color"] }, { type: IconComponent, selector: "stream-icon", inputs: ["icon", "size"] }], directives: [{ type: i6.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i6.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i6.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet"] }], pipes: { "async": i6.AsyncPipe, "translate":
|
|
2608
|
+
ChannelListComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.5", type: ChannelListComponent, selector: "stream-channel-list", inputs: { customChannelPreviewTemplate: "customChannelPreviewTemplate" }, 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-container\n *ngIf=\"customChannelPreviewTemplate; else defaultTemplate\"\n >\n <div (click)=\"channelSelected()\" (keyup.enter)=\"channelSelected()\">\n <ng-container\n *ngTemplateOutlet=\"\n customChannelPreviewTemplate;\n context: { channel: channel }\n \"\n ></ng-container>\n </div>\n </ng-container>\n <ng-template #defaultTemplate>\n <stream-channel-preview\n data-testclass=\"channel-preview\"\n [channel]=\"channel\"\n (click)=\"channelSelected()\"\n (keyup.enter)=\"channelSelected()\"\n ></stream-channel-preview>\n </ng-template>\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></stream-loading-indicator\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 icon=\"connection-error\"></stream-icon>\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: LoadingIndicatorComponent, selector: "stream-loading-indicator", inputs: ["size", "color"] }, { type: IconComponent, selector: "stream-icon", inputs: ["icon", "size"] }], directives: [{ type: i6.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i6.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i6.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet"] }], pipes: { "async": i6.AsyncPipe, "translate": i2.TranslatePipe } });
|
|
2292
2609
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: ChannelListComponent, decorators: [{
|
|
2293
2610
|
type: Component,
|
|
2294
2611
|
args: [{
|
|
@@ -2439,7 +2756,7 @@ class MessageReactionsComponent {
|
|
|
2439
2756
|
}
|
|
2440
2757
|
}
|
|
2441
2758
|
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 });
|
|
2442
|
-
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
|
|
2759
|
+
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: AvatarComponent, selector: "stream-avatar", inputs: ["name", "imageUrl", "size"] }], directives: [{ type: i6.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i6.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i6.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }] });
|
|
2443
2760
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: MessageReactionsComponent, decorators: [{
|
|
2444
2761
|
type: Component,
|
|
2445
2762
|
args: [{
|
|
@@ -2591,6 +2908,9 @@ class MessageComponent {
|
|
|
2591
2908
|
}
|
|
2592
2909
|
if (!this.message.mentioned_users ||
|
|
2593
2910
|
this.message.mentioned_users.length === 0) {
|
|
2911
|
+
// Wrap emojis in span to display emojis correctly in Chrome https://bugs.chromium.org/p/chromium/issues/detail?id=596223
|
|
2912
|
+
const regex = new RegExp(emojiRegex(), 'g');
|
|
2913
|
+
content = content.replace(regex, (match) => `<span class="str-chat__emoji-display-fix">${match}</span>`);
|
|
2594
2914
|
this.messageTextParts = [{ content, type: 'text' }];
|
|
2595
2915
|
}
|
|
2596
2916
|
else {
|
|
@@ -2618,7 +2938,7 @@ class MessageComponent {
|
|
|
2618
2938
|
}
|
|
2619
2939
|
}
|
|
2620
2940
|
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 });
|
|
2621
|
-
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: i1.TranslateDirective, selector: "[translate],[ngx-translate]", inputs: ["translate", "translateParams"] }], pipes: { "translate": i1.TranslatePipe } });
|
|
2941
|
+
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 } });
|
|
2622
2942
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: MessageComponent, decorators: [{
|
|
2623
2943
|
type: Component,
|
|
2624
2944
|
args: [{
|
|
@@ -2650,14 +2970,29 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImpor
|
|
|
2650
2970
|
}] } });
|
|
2651
2971
|
|
|
2652
2972
|
class TextareaComponent {
|
|
2653
|
-
constructor() {
|
|
2973
|
+
constructor(emojiInputService) {
|
|
2974
|
+
this.emojiInputService = emojiInputService;
|
|
2654
2975
|
this.class = 'str-chat__textarea';
|
|
2655
2976
|
this.value = '';
|
|
2656
2977
|
this.valueChange = new EventEmitter();
|
|
2657
2978
|
this.send = new EventEmitter();
|
|
2979
|
+
this.subscriptions = [];
|
|
2980
|
+
this.subscriptions.push(this.emojiInputService.emojiInput$.subscribe((emoji) => {
|
|
2981
|
+
this.messageInput.nativeElement.focus();
|
|
2982
|
+
const { selectionStart } = this.messageInput.nativeElement;
|
|
2983
|
+
this.messageInput.nativeElement.setRangeText(emoji);
|
|
2984
|
+
this.messageInput.nativeElement.selectionStart =
|
|
2985
|
+
selectionStart + emoji.length;
|
|
2986
|
+
this.messageInput.nativeElement.selectionEnd =
|
|
2987
|
+
selectionStart + emoji.length;
|
|
2988
|
+
this.inputChanged();
|
|
2989
|
+
}));
|
|
2658
2990
|
}
|
|
2659
2991
|
// eslint-disable-next-line @angular-eslint/no-empty-lifecycle-method
|
|
2660
2992
|
ngOnChanges() { }
|
|
2993
|
+
ngOnDestroy() {
|
|
2994
|
+
this.subscriptions.forEach((s) => s.unsubscribe());
|
|
2995
|
+
}
|
|
2661
2996
|
inputChanged() {
|
|
2662
2997
|
this.valueChange.emit(this.messageInput.nativeElement.value);
|
|
2663
2998
|
}
|
|
@@ -2666,8 +3001,8 @@ class TextareaComponent {
|
|
|
2666
3001
|
this.send.next();
|
|
2667
3002
|
}
|
|
2668
3003
|
}
|
|
2669
|
-
TextareaComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: TextareaComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2670
|
-
TextareaComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.5", type: TextareaComponent, selector: "stream-textarea", inputs: { value: "value" }, outputs: { valueChange: "valueChange", send: "send" }, host: { properties: { "class": "this.class" } }, viewQueries: [{ propertyName: "messageInput", first: true, predicate: ["input"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<textarea\n [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\"\n rows=\"1\"\n (input)=\"inputChanged()\"\n (keydown.enter)=\"sent($event)\"\n></textarea>\n", pipes: { "translate":
|
|
3004
|
+
TextareaComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: TextareaComponent, deps: [{ token: EmojiInputService }], target: i0.ɵɵFactoryTarget.Component });
|
|
3005
|
+
TextareaComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.5", type: TextareaComponent, selector: "stream-textarea", inputs: { value: "value" }, outputs: { valueChange: "valueChange", send: "send" }, host: { properties: { "class": "this.class" } }, viewQueries: [{ propertyName: "messageInput", first: true, predicate: ["input"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<textarea\n [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></textarea>\n", pipes: { "translate": i2.TranslatePipe } });
|
|
2671
3006
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: TextareaComponent, decorators: [{
|
|
2672
3007
|
type: Component,
|
|
2673
3008
|
args: [{
|
|
@@ -2675,7 +3010,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImpor
|
|
|
2675
3010
|
templateUrl: './textarea.component.html',
|
|
2676
3011
|
styles: [],
|
|
2677
3012
|
}]
|
|
2678
|
-
}], ctorParameters: function () { return []; }, propDecorators: { class: [{
|
|
3013
|
+
}], ctorParameters: function () { return [{ type: EmojiInputService }]; }, propDecorators: { class: [{
|
|
2679
3014
|
type: HostBinding
|
|
2680
3015
|
}], value: [{
|
|
2681
3016
|
type: Input
|
|
@@ -2688,8 +3023,16 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImpor
|
|
|
2688
3023
|
args: ['input']
|
|
2689
3024
|
}] } });
|
|
2690
3025
|
|
|
3026
|
+
/**
|
|
3027
|
+
* The `TransliterationService` wraps the [@sindresorhus/transliterate](https://www.npmjs.com/package/@sindresorhus/transliterate) library
|
|
3028
|
+
*/
|
|
2691
3029
|
class TransliterationService {
|
|
2692
3030
|
constructor() { }
|
|
3031
|
+
/**
|
|
3032
|
+
*
|
|
3033
|
+
* @param s the string to be transliterated
|
|
3034
|
+
* @returns the result of the transliteration
|
|
3035
|
+
*/
|
|
2693
3036
|
transliterate(s) {
|
|
2694
3037
|
return transliterate(s);
|
|
2695
3038
|
}
|
|
@@ -2702,10 +3045,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImpor
|
|
|
2702
3045
|
}], ctorParameters: function () { return []; } });
|
|
2703
3046
|
|
|
2704
3047
|
class AutocompleteTextareaComponent {
|
|
2705
|
-
constructor(channelService, chatClientService, transliterationService) {
|
|
3048
|
+
constructor(channelService, chatClientService, transliterationService, emojiInputService) {
|
|
2706
3049
|
this.channelService = channelService;
|
|
2707
3050
|
this.chatClientService = chatClientService;
|
|
2708
3051
|
this.transliterationService = transliterationService;
|
|
3052
|
+
this.emojiInputService = emojiInputService;
|
|
2709
3053
|
this.class = 'str-chat__textarea';
|
|
2710
3054
|
this.value = '';
|
|
2711
3055
|
this.areMentionsEnabled = true;
|
|
@@ -2753,6 +3097,16 @@ class AutocompleteTextareaComponent {
|
|
|
2753
3097
|
this.userMentions.next([...this.mentionedUsers]);
|
|
2754
3098
|
void this.updateMentionOptions(this.searchTerm$.getValue());
|
|
2755
3099
|
}));
|
|
3100
|
+
this.subscriptions.push(this.emojiInputService.emojiInput$.subscribe((emoji) => {
|
|
3101
|
+
this.messageInput.nativeElement.focus();
|
|
3102
|
+
const { selectionStart } = this.messageInput.nativeElement;
|
|
3103
|
+
this.messageInput.nativeElement.setRangeText(emoji);
|
|
3104
|
+
this.messageInput.nativeElement.selectionStart =
|
|
3105
|
+
selectionStart + emoji.length;
|
|
3106
|
+
this.messageInput.nativeElement.selectionEnd =
|
|
3107
|
+
selectionStart + emoji.length;
|
|
3108
|
+
this.inputChanged();
|
|
3109
|
+
}));
|
|
2756
3110
|
this.autocompleteConfig.mentions = [
|
|
2757
3111
|
this.userMentionConfig,
|
|
2758
3112
|
this.slashCommandConfig,
|
|
@@ -2851,8 +3205,8 @@ class AutocompleteTextareaComponent {
|
|
|
2851
3205
|
}
|
|
2852
3206
|
}
|
|
2853
3207
|
}
|
|
2854
|
-
AutocompleteTextareaComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: AutocompleteTextareaComponent, deps: [{ token: ChannelService }, { token: ChatClientService }, { token: TransliterationService }], target: i0.ɵɵFactoryTarget.Component });
|
|
2855
|
-
AutocompleteTextareaComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.5", type: AutocompleteTextareaComponent, selector: "stream-autocomplete-textarea", inputs: { value: "value", areMentionsEnabled: "areMentionsEnabled", mentionAutocompleteItemTemplate: "mentionAutocompleteItemTemplate", commandAutocompleteItemTemplate: "commandAutocompleteItemTemplate", 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\"\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\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>\n <span data-testclass=\"username\" class=\"str-chat__user-item--name\">{{\n item.autocompleteLabel\n }}</span>\n </div>\n</ng-template>\n", components: [{ type: AvatarComponent, selector: "stream-avatar", inputs: ["name", "imageUrl", "size"] }], directives: [{ type:
|
|
3208
|
+
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 });
|
|
3209
|
+
AutocompleteTextareaComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.5", type: AutocompleteTextareaComponent, selector: "stream-autocomplete-textarea", inputs: { value: "value", areMentionsEnabled: "areMentionsEnabled", mentionAutocompleteItemTemplate: "mentionAutocompleteItemTemplate", commandAutocompleteItemTemplate: "commandAutocompleteItemTemplate", 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\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>\n <span data-testclass=\"username\" class=\"str-chat__user-item--name\">{{\n item.autocompleteLabel\n }}</span>\n </div>\n</ng-template>\n", components: [{ type: AvatarComponent, selector: "stream-avatar", inputs: ["name", "imageUrl", "size"] }], directives: [{ type: i6$1.MentionDirective, selector: "[mention], [mentionConfig]", inputs: ["mentionConfig", "mention", "mentionListTemplate"], outputs: ["searchTerm", "itemSelected", "opened", "closed"] }, { type: i6.NgSwitch, selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { type: i6.NgSwitchCase, selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }, { type: i6.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet"] }], pipes: { "translate": i2.TranslatePipe } });
|
|
2856
3210
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: AutocompleteTextareaComponent, decorators: [{
|
|
2857
3211
|
type: Component,
|
|
2858
3212
|
args: [{
|
|
@@ -2860,7 +3214,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImpor
|
|
|
2860
3214
|
templateUrl: './autocomplete-textarea.component.html',
|
|
2861
3215
|
styles: [],
|
|
2862
3216
|
}]
|
|
2863
|
-
}], ctorParameters: function () { return [{ type: ChannelService }, { type: ChatClientService }, { type: TransliterationService }]; }, propDecorators: { class: [{
|
|
3217
|
+
}], ctorParameters: function () { return [{ type: ChannelService }, { type: ChatClientService }, { type: TransliterationService }, { type: EmojiInputService }]; }, propDecorators: { class: [{
|
|
2864
3218
|
type: HostBinding
|
|
2865
3219
|
}], value: [{
|
|
2866
3220
|
type: Input
|
|
@@ -3003,6 +3357,8 @@ class MessageListComponent {
|
|
|
3003
3357
|
}
|
|
3004
3358
|
this.parentMessage = message;
|
|
3005
3359
|
}));
|
|
3360
|
+
this.usersTypingInChannel$ = this.channelService.usersTypingInChannel$;
|
|
3361
|
+
this.usersTypingInThread$ = this.channelService.usersTypingInThread$;
|
|
3006
3362
|
}
|
|
3007
3363
|
ngOnInit() {
|
|
3008
3364
|
this.setMessages$();
|
|
@@ -3042,9 +3398,17 @@ class MessageListComponent {
|
|
|
3042
3398
|
ngOnDestroy() {
|
|
3043
3399
|
this.subscriptions.forEach((s) => s.unsubscribe());
|
|
3044
3400
|
}
|
|
3401
|
+
get usersTyping$() {
|
|
3402
|
+
return this.mode === 'thread'
|
|
3403
|
+
? this.usersTypingInThread$
|
|
3404
|
+
: this.usersTypingInChannel$;
|
|
3405
|
+
}
|
|
3045
3406
|
trackByMessageId(index, item) {
|
|
3046
3407
|
return item.id;
|
|
3047
3408
|
}
|
|
3409
|
+
trackByUserId(index, user) {
|
|
3410
|
+
return user.id;
|
|
3411
|
+
}
|
|
3048
3412
|
scrollToBottom() {
|
|
3049
3413
|
this.scrollContainer.nativeElement.scrollTop =
|
|
3050
3414
|
this.scrollContainer.nativeElement.scrollHeight;
|
|
@@ -3150,7 +3514,7 @@ class MessageListComponent {
|
|
|
3150
3514
|
}
|
|
3151
3515
|
}
|
|
3152
3516
|
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 });
|
|
3153
|
-
MessageListComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.5", type: MessageListComponent, selector: "stream-message-list", inputs: { messageTemplate: "messageTemplate", messageInputTemplate: "messageInputTemplate", mentionTemplate: "mentionTemplate", areReactionsEnabled: "areReactionsEnabled", enabledMessageActionsInput: ["enabledMessageActions", "enabledMessageActionsInput"], mode: "mode" }, host: { properties: { "class": "this.class" } }, viewQueries: [{ propertyName: "scrollContainer", first: true, predicate: ["scrollContainer"], descendants: true }, { propertyName: "parentMessageElement", first: true, predicate: ["parentMessageElement"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div\n #scrollContainer\n data-testid=\"scroll-container\"\n class=\"str-chat__list\"\n (scroll)=\"scrolled()\"\n>\n <div class=\"str-chat__reverse-infinite-scroll\">\n <ul class=\"str-chat__ul\">\n <li\n #parentMessageElement\n *ngIf=\"mode === 'thread'\"\n data-testid=\"parent-message\"\n >\n <ng-container\n *ngTemplateOutlet=\"\n messageTemplateContainer;\n context: { message: parentMessage }\n \"\n ></ng-container>\n <div class=\"str-chat__thread-start\" translate>\n streamChat.Start of a new thread\n </div>\n </li>\n <li\n data-testclass=\"message\"\n *ngFor=\"\n let message of messages$ | async;\n let i = index;\n trackBy: trackByMessageId\n \"\n class=\"str-chat__li str-chat__li--{{ groupStyles[i] }}\"\n >\n <ng-container\n *ngTemplateOutlet=\"\n messageTemplateContainer;\n context: { message: message }\n \"\n ></ng-container>\n </li>\n </ul>\n </div>\n</div>\n<div class=\"str-chat__list-notifications\">\n <button\n data-testid=\"scroll-to-bottom\"\n *ngIf=\"isUserScrolledUp\"\n class=\"\n str-chat__message-notification\n str-chat__message-notification-right\n str-chat__message-notification-scroll-down\n \"\n (keyup.enter)=\"scrollToBottom()\"\n (click)=\"scrollToBottom()\"\n >\n <div\n *ngIf=\"unreadMessageCount > 0\"\n class=\"\n str-chat__message-notification\n str-chat__message-notification-scroll-down-unread-count\n \"\n >\n {{ unreadMessageCount }}\n </div>\n </button>\n</div>\n\n<ng-template #messageTemplateContainer let-message=\"message\">\n <ng-container *ngIf=\"messageTemplate; else defaultMessageTemplate\">\n <ng-container\n *ngTemplateOutlet=\"\n messageTemplate;\n context: {\n message: message,\n areReactionsEnabled: areReactionsEnabled,\n canReactToMessage: canReactToMessage,\n lastSentMessageId: !!(\n lastSentMessageId && message?.id === lastSentMessageId\n ),\n canReceiveReadEvents: canReceiveReadEvents,\n messageInputTemplate: messageInputTemplate,\n mentionTemplate: mentionTemplate,\n mode: mode\n }\n \"\n ></ng-container>\n </ng-container>\n <ng-template #defaultMessageTemplate>\n <stream-message\n [message]=\"message\"\n [areReactionsEnabled]=\"areReactionsEnabled\"\n [canReactToMessage]=\"canReactToMessage\"\n [isLastSentMessage]=\"\n !!(lastSentMessageId && message?.id === lastSentMessageId)\n \"\n [enabledMessageActions]=\"enabledMessageActions\"\n [canReceiveReadEvents]=\"canReceiveReadEvents\"\n [messageInputTemplate]=\"messageInputTemplate\"\n [mentionTemplate]=\"mentionTemplate\"\n [mode]=\"mode\"\n ></stream-message>\n </ng-template>\n</ng-template>\n", components: [{ type: MessageComponent, selector: "stream-message", inputs: ["messageInputTemplate", "mentionTemplate", "message", "enabledMessageActions", "areReactionsEnabled", "canReactToMessage", "isLastSentMessage", "canReceiveReadEvents", "mode"] }], directives: [{ type: i6.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i6.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet"] }, { type:
|
|
3517
|
+
MessageListComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.5", type: MessageListComponent, selector: "stream-message-list", inputs: { messageTemplate: "messageTemplate", messageInputTemplate: "messageInputTemplate", mentionTemplate: "mentionTemplate", typingIndicatorTemplate: "typingIndicatorTemplate", areReactionsEnabled: "areReactionsEnabled", enabledMessageActionsInput: ["enabledMessageActions", "enabledMessageActionsInput"], mode: "mode" }, host: { properties: { "class": "this.class" } }, viewQueries: [{ propertyName: "scrollContainer", first: true, predicate: ["scrollContainer"], descendants: true }, { propertyName: "parentMessageElement", first: true, predicate: ["parentMessageElement"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div\n #scrollContainer\n data-testid=\"scroll-container\"\n class=\"str-chat__list\"\n (scroll)=\"scrolled()\"\n>\n <div class=\"str-chat__reverse-infinite-scroll\">\n <ul class=\"str-chat__ul\">\n <li\n #parentMessageElement\n *ngIf=\"mode === 'thread'\"\n data-testid=\"parent-message\"\n >\n <ng-container\n *ngTemplateOutlet=\"\n messageTemplateContainer;\n context: { message: parentMessage }\n \"\n ></ng-container>\n <div class=\"str-chat__thread-start\" translate>\n streamChat.Start of a new thread\n </div>\n </li>\n <li\n data-testclass=\"message\"\n *ngFor=\"\n let message of messages$ | async;\n let i = index;\n trackBy: trackByMessageId\n \"\n class=\"str-chat__li str-chat__li--{{ groupStyles[i] }}\"\n >\n <ng-container\n *ngTemplateOutlet=\"\n messageTemplateContainer;\n context: { message: message }\n \"\n ></ng-container>\n </li>\n </ul>\n <ng-container *ngIf=\"typingIndicatorTemplate; else defaultTypingIndicator\">\n <ng-container\n *ngTemplateOutlet=\"\n typingIndicatorTemplate;\n context: { usersTyping$: usersTyping$ }\n \"\n ></ng-container>\n </ng-container>\n <ng-template #defaultTypingIndicator>\n <div\n *ngIf=\"(usersTyping$ | async)?.length\"\n data-testid=\"typing-indicator\"\n class=\"str-chat__typing-indicator str-chat__typing-indicator--typing\"\n >\n <stream-avatar\n *ngFor=\"let user of usersTyping$ | async; trackBy: trackByUserId\"\n [name]=\"user.name || user.id\"\n [imageUrl]=\"user.image\"\n ></stream-avatar>\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 </div>\n</div>\n<div class=\"str-chat__list-notifications\">\n <button\n data-testid=\"scroll-to-bottom\"\n *ngIf=\"isUserScrolledUp\"\n class=\"\n str-chat__message-notification\n str-chat__message-notification-right\n str-chat__message-notification-scroll-down\n \"\n (keyup.enter)=\"scrollToBottom()\"\n (click)=\"scrollToBottom()\"\n >\n <div\n *ngIf=\"unreadMessageCount > 0\"\n class=\"\n str-chat__message-notification\n str-chat__message-notification-scroll-down-unread-count\n \"\n >\n {{ unreadMessageCount }}\n </div>\n </button>\n</div>\n\n<ng-template #messageTemplateContainer let-message=\"message\">\n <ng-container *ngIf=\"messageTemplate; else defaultMessageTemplate\">\n <ng-container\n *ngTemplateOutlet=\"\n messageTemplate;\n context: {\n message: message,\n areReactionsEnabled: areReactionsEnabled,\n canReactToMessage: canReactToMessage,\n lastSentMessageId: !!(\n lastSentMessageId && message?.id === lastSentMessageId\n ),\n canReceiveReadEvents: canReceiveReadEvents,\n messageInputTemplate: messageInputTemplate,\n mentionTemplate: mentionTemplate,\n mode: mode\n }\n \"\n ></ng-container>\n </ng-container>\n <ng-template #defaultMessageTemplate>\n <stream-message\n [message]=\"message\"\n [areReactionsEnabled]=\"areReactionsEnabled\"\n [canReactToMessage]=\"canReactToMessage\"\n [isLastSentMessage]=\"\n !!(lastSentMessageId && message?.id === lastSentMessageId)\n \"\n [enabledMessageActions]=\"enabledMessageActions\"\n [canReceiveReadEvents]=\"canReceiveReadEvents\"\n [messageInputTemplate]=\"messageInputTemplate\"\n [mentionTemplate]=\"mentionTemplate\"\n [mode]=\"mode\"\n ></stream-message>\n </ng-template>\n</ng-template>\n", components: [{ type: AvatarComponent, selector: "stream-avatar", inputs: ["name", "imageUrl", "size"] }, { type: MessageComponent, selector: "stream-message", inputs: ["messageInputTemplate", "mentionTemplate", "message", "enabledMessageActions", "areReactionsEnabled", "canReactToMessage", "isLastSentMessage", "canReceiveReadEvents", "mode"] }], directives: [{ type: i6.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i6.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet"] }, { type: i2.TranslateDirective, selector: "[translate],[ngx-translate]", inputs: ["translate", "translateParams"] }, { type: i6.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }], pipes: { "async": i6.AsyncPipe } });
|
|
3154
3518
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: MessageListComponent, decorators: [{
|
|
3155
3519
|
type: Component,
|
|
3156
3520
|
args: [{
|
|
@@ -3164,6 +3528,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImpor
|
|
|
3164
3528
|
type: Input
|
|
3165
3529
|
}], mentionTemplate: [{
|
|
3166
3530
|
type: Input
|
|
3531
|
+
}], typingIndicatorTemplate: [{
|
|
3532
|
+
type: Input
|
|
3167
3533
|
}], areReactionsEnabled: [{
|
|
3168
3534
|
type: Input
|
|
3169
3535
|
}], enabledMessageActionsInput: [{
|
|
@@ -3201,7 +3567,7 @@ class ThreadComponent {
|
|
|
3201
3567
|
}
|
|
3202
3568
|
}
|
|
3203
3569
|
ThreadComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: ThreadComponent, deps: [{ token: ChannelService }], target: i0.ɵɵFactoryTarget.Component });
|
|
3204
|
-
ThreadComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.5", type: ThreadComponent, selector: "stream-thread", host: { properties: { "class": "this.class" } }, ngImport: i0, template: "<div class=\"str-chat__thread-header\">\n <div class=\"str-chat__thread-header-details\">\n <strong translate>streamChat.Thread</strong>\n <small data-testid=\"reply-count\">\n {{parentMessage?.reply_count === 1 ? ('streamChat.1 reply' | translate) : ('streamChat.{{ replyCount }}\n replies' | translate:replyCountParam)}}\n </small>\n </div>\n <button\n class=\"str-chat__square-button\"\n data-testid=\"close-button\"\n (click)=\"closeThread()\"\n >\n <stream-icon icon=\"close-no-outline\"></stream-icon>\n </button>\n</div>\n<ng-content select='[name=\"thread-message-list\"]'></ng-content>\n<div class=\"str-chat__small-message-input__wrapper\">\n <ng-content select='[name=\"thread-message-input\"]'></ng-content>\n</div>\n", components: [{ type: IconComponent, selector: "stream-icon", inputs: ["icon", "size"] }], directives: [{ type:
|
|
3570
|
+
ThreadComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.5", type: ThreadComponent, selector: "stream-thread", host: { properties: { "class": "this.class" } }, ngImport: i0, template: "<div class=\"str-chat__thread-header\">\n <div class=\"str-chat__thread-header-details\">\n <strong translate>streamChat.Thread</strong>\n <small data-testid=\"reply-count\">\n {{parentMessage?.reply_count === 1 ? ('streamChat.1 reply' | translate) : ('streamChat.{{ replyCount }}\n replies' | translate:replyCountParam)}}\n </small>\n </div>\n <button\n class=\"str-chat__square-button\"\n data-testid=\"close-button\"\n (click)=\"closeThread()\"\n >\n <stream-icon icon=\"close-no-outline\"></stream-icon>\n </button>\n</div>\n<ng-content select='[name=\"thread-message-list\"]'></ng-content>\n<div class=\"str-chat__small-message-input__wrapper\">\n <ng-content select='[name=\"thread-message-input\"]'></ng-content>\n</div>\n", components: [{ type: IconComponent, selector: "stream-icon", inputs: ["icon", "size"] }], directives: [{ type: i2.TranslateDirective, selector: "[translate],[ngx-translate]", inputs: ["translate", "translateParams"] }], pipes: { "translate": i2.TranslatePipe } });
|
|
3205
3571
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: ThreadComponent, decorators: [{
|
|
3206
3572
|
type: Component,
|
|
3207
3573
|
args: [{
|
|
@@ -3372,5 +3738,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImpor
|
|
|
3372
3738
|
* Generated bundle index. Do not edit.
|
|
3373
3739
|
*/
|
|
3374
3740
|
|
|
3375
|
-
export { AttachmentListComponent, AttachmentPreviewListComponent, AttachmentService, AutocompleteTextareaComponent, AvatarComponent, ChannelComponent, ChannelHeaderComponent, ChannelListComponent, ChannelListToggleService, ChannelPreviewComponent, ChannelService, ChatClientService, IconComponent, ImageLoadService, LoadingIndicatorComponent, MessageActionsBoxComponent, MessageComponent, MessageInputComponent, MessageInputConfigService, MessageListComponent, MessageReactionsComponent, ModalComponent, NotificationComponent, NotificationListComponent, NotificationService, StreamAutocompleteTextareaModule, StreamAvatarModule, StreamChatModule, StreamI18nService, StreamTextareaModule, TextareaComponent, TextareaDirective, ThemeService, ThreadComponent, TransliterationService, createMessagePreview, getDeviceWidth, getGroupStyles, getReadBy, getReadByText, isImageAttachment, isImageFile, parseDate, textareaInjectionToken };
|
|
3741
|
+
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 };
|
|
3376
3742
|
//# sourceMappingURL=stream-chat-angular.js.map
|