stream-chat-angular 2.8.2 → 2.12.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/i18n/en.d.ts +2 -0
- package/assets/version.d.ts +1 -1
- package/bundles/stream-chat-angular.umd.js +804 -338
- package/bundles/stream-chat-angular.umd.js.map +1 -1
- package/esm2015/assets/i18n/en.js +3 -1
- package/esm2015/assets/version.js +2 -2
- package/esm2015/lib/attachment-list/attachment-list.component.js +21 -8
- package/esm2015/lib/channel/channel.component.js +3 -2
- package/esm2015/lib/channel.service.js +191 -38
- package/esm2015/lib/chat-client.service.js +6 -1
- package/esm2015/lib/icon/icon.component.js +2 -2
- package/esm2015/lib/message/message.component.js +67 -42
- package/esm2015/lib/message-actions-box/message-actions-box.component.js +20 -9
- package/esm2015/lib/message-input/autocomplete-textarea/autocomplete-textarea.component.js +35 -9
- package/esm2015/lib/message-input/message-input-config.service.js +1 -1
- package/esm2015/lib/message-input/message-input.component.js +69 -13
- package/esm2015/lib/message-input/textarea.directive.js +10 -2
- package/esm2015/lib/message-input/textarea.interface.js +1 -1
- package/esm2015/lib/message-list/message-list.component.js +130 -55
- package/esm2015/lib/message-preview.js +4 -2
- package/esm2015/lib/stream-chat.module.js +8 -3
- package/esm2015/lib/thread/thread.component.js +37 -0
- package/esm2015/lib/types.js +1 -1
- package/esm2015/public-api.js +2 -1
- package/fesm2015/stream-chat-angular.js +659 -250
- package/fesm2015/stream-chat-angular.js.map +1 -1
- package/lib/attachment-list/attachment-list.component.d.ts +8 -3
- package/lib/channel/channel.component.d.ts +2 -1
- package/lib/channel.service.d.ts +23 -7
- package/lib/chat-client.service.d.ts +1 -0
- package/lib/icon/icon.component.d.ts +1 -1
- package/lib/message/message.component.d.ts +26 -8
- package/lib/message-actions-box/message-actions-box.component.d.ts +4 -1
- package/lib/message-input/autocomplete-textarea/autocomplete-textarea.component.d.ts +6 -3
- package/lib/message-input/message-input-config.service.d.ts +2 -1
- package/lib/message-input/message-input.component.d.ts +9 -2
- package/lib/message-input/textarea.directive.d.ts +3 -2
- package/lib/message-input/textarea.interface.d.ts +2 -1
- package/lib/message-list/message-list.component.d.ts +21 -7
- package/lib/message-preview.d.ts +1 -1
- package/lib/stream-chat.module.d.ts +5 -4
- package/lib/thread/thread.component.d.ts +18 -0
- package/lib/types.d.ts +7 -1
- package/package.json +2 -11
- package/public-api.d.ts +1 -0
- package/src/assets/i18n/en.ts +4 -0
- package/src/assets/version.ts +1 -1
|
@@ -1,22 +1,22 @@
|
|
|
1
1
|
import { __awaiter } from 'tslib';
|
|
2
2
|
import * as i0 from '@angular/core';
|
|
3
3
|
import { Injectable, Component, Input, InjectionToken, EventEmitter, Directive, Output, Inject, ViewChild, HostBinding, NgModule } from '@angular/core';
|
|
4
|
-
import { BehaviorSubject, ReplaySubject,
|
|
4
|
+
import { BehaviorSubject, ReplaySubject, combineLatest, Subject, of } from 'rxjs';
|
|
5
5
|
import { StreamChat } from 'stream-chat';
|
|
6
|
-
import { map, first, catchError, startWith, distinctUntilChanged,
|
|
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 i1 from '@ngx-translate/core';
|
|
9
9
|
import { TranslateModule } from '@ngx-translate/core';
|
|
10
|
-
import * as
|
|
10
|
+
import * as i6 from '@angular/common';
|
|
11
11
|
import { CommonModule } from '@angular/common';
|
|
12
|
+
import prettybytes from 'pretty-bytes';
|
|
12
13
|
import Dayjs from 'dayjs';
|
|
13
14
|
import calendar from 'dayjs/plugin/calendar';
|
|
14
|
-
import prettybytes from 'pretty-bytes';
|
|
15
15
|
import transliterate from '@stream-io/transliterate';
|
|
16
16
|
import * as i5 from 'angular-mentions';
|
|
17
17
|
import { MentionModule } from 'angular-mentions';
|
|
18
18
|
|
|
19
|
-
const version = '2.
|
|
19
|
+
const version = '2.12.0';
|
|
20
20
|
|
|
21
21
|
class NotificationService {
|
|
22
22
|
constructor() {
|
|
@@ -105,6 +105,11 @@ class ChatClientService {
|
|
|
105
105
|
});
|
|
106
106
|
});
|
|
107
107
|
}
|
|
108
|
+
disconnectUser() {
|
|
109
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
110
|
+
yield this.chatClient.disconnectUser();
|
|
111
|
+
});
|
|
112
|
+
}
|
|
108
113
|
getAppSettings() {
|
|
109
114
|
return __awaiter(this, void 0, void 0, function* () {
|
|
110
115
|
if (this.appSettingsSubject.getValue()) {
|
|
@@ -144,7 +149,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImpor
|
|
|
144
149
|
}]
|
|
145
150
|
}], ctorParameters: function () { return [{ type: i0.NgZone }, { type: NotificationService }]; } });
|
|
146
151
|
|
|
147
|
-
const createMessagePreview = (user, text, attachments, mentionedUsers) => {
|
|
152
|
+
const createMessagePreview = (user, text, attachments = [], mentionedUsers = [], parentId = undefined, quotedMessageId = undefined) => {
|
|
148
153
|
const clientSideId = `${user.id}-${v4()}`;
|
|
149
154
|
return {
|
|
150
155
|
__html: text,
|
|
@@ -158,6 +163,8 @@ const createMessagePreview = (user, text, attachments, mentionedUsers) => {
|
|
|
158
163
|
user,
|
|
159
164
|
attachments,
|
|
160
165
|
mentioned_users: mentionedUsers,
|
|
166
|
+
parent_id: parentId,
|
|
167
|
+
quoted_message_id: quotedMessageId,
|
|
161
168
|
};
|
|
162
169
|
};
|
|
163
170
|
|
|
@@ -183,31 +190,52 @@ class ChannelService {
|
|
|
183
190
|
this.activeChannelMessagesSubject = new BehaviorSubject([]);
|
|
184
191
|
this.hasMoreChannelsSubject = new ReplaySubject(1);
|
|
185
192
|
this.activeChannelSubscriptions = [];
|
|
193
|
+
this.activeParentMessageIdSubject = new BehaviorSubject(undefined);
|
|
194
|
+
this.activeThreadMessagesSubject = new BehaviorSubject([]);
|
|
195
|
+
this.messagePageSize = 25;
|
|
196
|
+
this.messageToQuoteSubject = new BehaviorSubject(undefined);
|
|
186
197
|
this.channelListSetter = (channels) => {
|
|
187
198
|
this.channelsSubject.next(channels);
|
|
188
199
|
};
|
|
189
200
|
this.messageListSetter = (messages) => {
|
|
190
201
|
this.activeChannelMessagesSubject.next(messages);
|
|
191
202
|
};
|
|
203
|
+
this.threadListSetter = (messages) => {
|
|
204
|
+
this.activeThreadMessagesSubject.next(messages);
|
|
205
|
+
};
|
|
206
|
+
this.parentMessageSetter = (message) => {
|
|
207
|
+
this.activeParentMessageIdSubject.next(message === null || message === void 0 ? void 0 : message.id);
|
|
208
|
+
};
|
|
192
209
|
this.channels$ = this.channelsSubject.asObservable();
|
|
193
210
|
this.activeChannel$ = this.activeChannelSubject.asObservable();
|
|
194
211
|
this.activeChannelMessages$ = this.activeChannelMessagesSubject.pipe(map((messages) => {
|
|
195
212
|
const channel = this.activeChannelSubject.getValue();
|
|
196
|
-
return messages.map((message) =>
|
|
197
|
-
if (this.isStreamMessage(message) &&
|
|
198
|
-
this.isFormatMessageResponse(message)) {
|
|
199
|
-
return message;
|
|
200
|
-
}
|
|
201
|
-
else if (this.isFormatMessageResponse(message)) {
|
|
202
|
-
return Object.assign(Object.assign({}, message), { readBy: getReadBy(message, channel) });
|
|
203
|
-
}
|
|
204
|
-
else {
|
|
205
|
-
const formatMessage = this.formatMessage(message);
|
|
206
|
-
return Object.assign(Object.assign({}, formatMessage), { readBy: getReadBy(formatMessage, channel) });
|
|
207
|
-
}
|
|
208
|
-
});
|
|
213
|
+
return messages.map((message) => this.transformToStreamMessage(message, channel));
|
|
209
214
|
}));
|
|
210
215
|
this.hasMoreChannels$ = this.hasMoreChannelsSubject.asObservable();
|
|
216
|
+
this.activeParentMessageId$ =
|
|
217
|
+
this.activeParentMessageIdSubject.asObservable();
|
|
218
|
+
this.activeThreadMessages$ = this.activeThreadMessagesSubject.pipe(map((messages) => {
|
|
219
|
+
const channel = this.activeChannelSubject.getValue();
|
|
220
|
+
return messages.map((message) => this.transformToStreamMessage(message, channel));
|
|
221
|
+
}));
|
|
222
|
+
this.activeParentMessage$ = combineLatest([
|
|
223
|
+
this.activeChannelMessages$,
|
|
224
|
+
this.activeParentMessageId$,
|
|
225
|
+
]).pipe(map(([messages, parentMessageId]) => {
|
|
226
|
+
if (!parentMessageId) {
|
|
227
|
+
return undefined;
|
|
228
|
+
}
|
|
229
|
+
else {
|
|
230
|
+
return messages.find((m) => m.id === parentMessageId);
|
|
231
|
+
}
|
|
232
|
+
}), shareReplay());
|
|
233
|
+
this.messageToQuote$ = this.messageToQuoteSubject.asObservable();
|
|
234
|
+
this.chatClientService.connectionState$
|
|
235
|
+
.pipe(filter((s) => s === 'online'))
|
|
236
|
+
.subscribe(() => {
|
|
237
|
+
void this.setAsActiveParentMessage(undefined);
|
|
238
|
+
});
|
|
211
239
|
}
|
|
212
240
|
setAsActiveChannel(channel) {
|
|
213
241
|
const prevActiveChannel = this.activeChannelSubject.getValue();
|
|
@@ -221,25 +249,66 @@ class ChannelService {
|
|
|
221
249
|
void channel.markRead();
|
|
222
250
|
}
|
|
223
251
|
this.activeChannelMessagesSubject.next([...channel.state.messages]);
|
|
252
|
+
this.activeParentMessageIdSubject.next(undefined);
|
|
253
|
+
this.activeThreadMessagesSubject.next([]);
|
|
254
|
+
this.messageToQuoteSubject.next(undefined);
|
|
224
255
|
}
|
|
256
|
+
setAsActiveParentMessage(message) {
|
|
257
|
+
var _a;
|
|
258
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
259
|
+
const messageToQuote = this.messageToQuoteSubject.getValue();
|
|
260
|
+
if (messageToQuote && !!messageToQuote.parent_id) {
|
|
261
|
+
this.messageToQuoteSubject.next(undefined);
|
|
262
|
+
}
|
|
263
|
+
if (!message) {
|
|
264
|
+
this.activeParentMessageIdSubject.next(undefined);
|
|
265
|
+
this.activeThreadMessagesSubject.next([]);
|
|
266
|
+
}
|
|
267
|
+
else {
|
|
268
|
+
this.activeParentMessageIdSubject.next(message.id);
|
|
269
|
+
const activeChannel = this.activeChannelSubject.getValue();
|
|
270
|
+
const result = yield (activeChannel === null || activeChannel === void 0 ? void 0 : activeChannel.getReplies(message.id, {
|
|
271
|
+
limit: (_a = this.options) === null || _a === void 0 ? void 0 : _a.message_limit,
|
|
272
|
+
}));
|
|
273
|
+
this.activeThreadMessagesSubject.next((result === null || result === void 0 ? void 0 : result.messages) || []);
|
|
274
|
+
}
|
|
275
|
+
});
|
|
276
|
+
}
|
|
277
|
+
// load more thread replies
|
|
225
278
|
loadMoreMessages() {
|
|
226
|
-
var _a, _b, _c, _d;
|
|
279
|
+
var _a, _b, _c, _d, _e;
|
|
227
280
|
return __awaiter(this, void 0, void 0, function* () {
|
|
228
281
|
const activeChnannel = this.activeChannelSubject.getValue();
|
|
229
282
|
const lastMessageId = (_a = this.activeChannelMessagesSubject.getValue()[0]) === null || _a === void 0 ? void 0 : _a.id;
|
|
230
283
|
yield (activeChnannel === null || activeChnannel === void 0 ? void 0 : activeChnannel.query({
|
|
231
|
-
messages: { limit:
|
|
284
|
+
messages: { limit: (_b = this.options) === null || _b === void 0 ? void 0 : _b.message_limit, id_lt: lastMessageId },
|
|
232
285
|
members: { limit: 0 },
|
|
233
286
|
watchers: { limit: 0 },
|
|
234
287
|
}));
|
|
235
|
-
if (((
|
|
236
|
-
((
|
|
288
|
+
if (((_c = activeChnannel === null || activeChnannel === void 0 ? void 0 : activeChnannel.data) === null || _c === void 0 ? void 0 : _c.id) ===
|
|
289
|
+
((_e = (_d = this.activeChannelSubject.getValue()) === null || _d === void 0 ? void 0 : _d.data) === null || _e === void 0 ? void 0 : _e.id)) {
|
|
237
290
|
this.activeChannelMessagesSubject.next([
|
|
238
291
|
...activeChnannel.state.messages,
|
|
239
292
|
]);
|
|
240
293
|
}
|
|
241
294
|
});
|
|
242
295
|
}
|
|
296
|
+
loadMoreThreadReplies() {
|
|
297
|
+
var _a, _b;
|
|
298
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
299
|
+
const activeChnannel = this.activeChannelSubject.getValue();
|
|
300
|
+
const parentMessageId = this.activeParentMessageIdSubject.getValue();
|
|
301
|
+
if (!parentMessageId) {
|
|
302
|
+
return;
|
|
303
|
+
}
|
|
304
|
+
const lastMessageId = (_a = this.activeThreadMessagesSubject.getValue()[0]) === null || _a === void 0 ? void 0 : _a.id;
|
|
305
|
+
yield (activeChnannel === null || activeChnannel === void 0 ? void 0 : activeChnannel.getReplies(parentMessageId, {
|
|
306
|
+
limit: (_b = this.options) === null || _b === void 0 ? void 0 : _b.message_limit,
|
|
307
|
+
id_lt: lastMessageId,
|
|
308
|
+
}));
|
|
309
|
+
this.activeThreadMessagesSubject.next((activeChnannel === null || activeChnannel === void 0 ? void 0 : activeChnannel.state.threads[parentMessageId]) || []);
|
|
310
|
+
});
|
|
311
|
+
}
|
|
243
312
|
init(filters, sort, options) {
|
|
244
313
|
return __awaiter(this, void 0, void 0, function* () {
|
|
245
314
|
this.filters = filters;
|
|
@@ -249,13 +318,21 @@ class ChannelService {
|
|
|
249
318
|
state: true,
|
|
250
319
|
presence: true,
|
|
251
320
|
watch: true,
|
|
252
|
-
message_limit:
|
|
321
|
+
message_limit: this.messagePageSize,
|
|
253
322
|
};
|
|
254
323
|
this.sort = sort || { last_message_at: -1, updated_at: -1 };
|
|
255
324
|
yield this.queryChannels();
|
|
256
325
|
this.chatClientService.notification$.subscribe((notification) => void this.handleNotification(notification));
|
|
257
326
|
});
|
|
258
327
|
}
|
|
328
|
+
reset() {
|
|
329
|
+
this.activeChannelMessagesSubject.next([]);
|
|
330
|
+
this.activeChannelSubject.next(undefined);
|
|
331
|
+
this.activeParentMessageIdSubject.next(undefined);
|
|
332
|
+
this.activeThreadMessagesSubject.next([]);
|
|
333
|
+
this.channelsSubject.next(undefined);
|
|
334
|
+
this.selectMessageToQuote(undefined);
|
|
335
|
+
}
|
|
259
336
|
loadMoreChannels() {
|
|
260
337
|
return __awaiter(this, void 0, void 0, function* () {
|
|
261
338
|
this.options.offset = this.channels.length;
|
|
@@ -277,9 +354,9 @@ class ChannelService {
|
|
|
277
354
|
.getValue()) === null || _a === void 0 ? void 0 : _a.deleteReaction(messageId, reactionType));
|
|
278
355
|
});
|
|
279
356
|
}
|
|
280
|
-
sendMessage(text, attachments = [], mentionedUsers = []) {
|
|
357
|
+
sendMessage(text, attachments = [], mentionedUsers = [], parentId = undefined, quotedMessageId = undefined) {
|
|
281
358
|
return __awaiter(this, void 0, void 0, function* () {
|
|
282
|
-
const preview = createMessagePreview(this.chatClientService.chatClient.user, text, attachments, mentionedUsers);
|
|
359
|
+
const preview = createMessagePreview(this.chatClientService.chatClient.user, text, attachments, mentionedUsers, parentId, quotedMessageId);
|
|
283
360
|
const channel = this.activeChannelSubject.getValue();
|
|
284
361
|
preview.readBy = [];
|
|
285
362
|
channel.state.addMessageSorted(preview, true);
|
|
@@ -357,18 +434,64 @@ class ChannelService {
|
|
|
357
434
|
}
|
|
358
435
|
});
|
|
359
436
|
}
|
|
437
|
+
sendAction(messageId, formData) {
|
|
438
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
439
|
+
const channel = this.activeChannelSubject.getValue();
|
|
440
|
+
const response = yield channel.sendAction(messageId, formData);
|
|
441
|
+
if (response === null || response === void 0 ? void 0 : response.message) {
|
|
442
|
+
channel.state.addMessageSorted(Object.assign(Object.assign({}, response.message), { status: 'received' }));
|
|
443
|
+
const isThreadReply = !!response.message.parent_id;
|
|
444
|
+
isThreadReply
|
|
445
|
+
? this.activeThreadMessagesSubject.next([
|
|
446
|
+
...channel.state.threads[response.message.parent_id],
|
|
447
|
+
])
|
|
448
|
+
: this.activeChannelMessagesSubject.next([...channel.state.messages]);
|
|
449
|
+
}
|
|
450
|
+
else {
|
|
451
|
+
channel.state.removeMessage({ id: messageId });
|
|
452
|
+
if (this.activeChannelMessagesSubject
|
|
453
|
+
.getValue()
|
|
454
|
+
.find((m) => m.id === messageId)) {
|
|
455
|
+
this.activeChannelMessagesSubject.next([...channel.state.messages]);
|
|
456
|
+
}
|
|
457
|
+
else if (this.activeThreadMessagesSubject
|
|
458
|
+
.getValue()
|
|
459
|
+
.find((m) => m.id === messageId)) {
|
|
460
|
+
this.activeThreadMessagesSubject.next(channel.state.threads[this.activeParentMessageIdSubject.getValue()]);
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
});
|
|
464
|
+
}
|
|
465
|
+
selectMessageToQuote(message) {
|
|
466
|
+
this.messageToQuoteSubject.next(message);
|
|
467
|
+
}
|
|
360
468
|
sendMessageRequest(preview) {
|
|
361
469
|
var _a;
|
|
362
470
|
return __awaiter(this, void 0, void 0, function* () {
|
|
363
471
|
const channel = this.activeChannelSubject.getValue();
|
|
364
|
-
|
|
472
|
+
const isThreadReply = !!preview.parent_id;
|
|
473
|
+
isThreadReply
|
|
474
|
+
? this.activeThreadMessagesSubject.next([
|
|
475
|
+
...channel.state.threads[preview.parent_id],
|
|
476
|
+
])
|
|
477
|
+
: this.activeChannelMessagesSubject.next([...channel.state.messages]);
|
|
365
478
|
try {
|
|
366
|
-
yield channel.sendMessage({
|
|
479
|
+
const response = yield channel.sendMessage({
|
|
367
480
|
text: preview.text,
|
|
368
481
|
attachments: preview.attachments,
|
|
369
482
|
mentioned_users: (_a = preview.mentioned_users) === null || _a === void 0 ? void 0 : _a.map((u) => u.id),
|
|
370
483
|
id: preview.id,
|
|
484
|
+
parent_id: preview.parent_id,
|
|
485
|
+
quoted_message_id: preview.quoted_message_id,
|
|
371
486
|
});
|
|
487
|
+
if (response === null || response === void 0 ? void 0 : response.message) {
|
|
488
|
+
channel.state.addMessageSorted(Object.assign(Object.assign({}, response.message), { status: 'received' }), true);
|
|
489
|
+
isThreadReply
|
|
490
|
+
? this.activeThreadMessagesSubject.next([
|
|
491
|
+
...channel.state.threads[preview.parent_id],
|
|
492
|
+
])
|
|
493
|
+
: this.activeChannelMessagesSubject.next([...channel.state.messages]);
|
|
494
|
+
}
|
|
372
495
|
}
|
|
373
496
|
catch (error) {
|
|
374
497
|
const stringError = JSON.stringify(error);
|
|
@@ -376,7 +499,11 @@ class ChannelService {
|
|
|
376
499
|
? JSON.parse(stringError)
|
|
377
500
|
: {};
|
|
378
501
|
channel.state.addMessageSorted(Object.assign(Object.assign({}, preview), { errorStatusCode: parsedError.status || undefined, status: 'failed' }), true);
|
|
379
|
-
|
|
502
|
+
isThreadReply
|
|
503
|
+
? this.activeThreadMessagesSubject.next([
|
|
504
|
+
...channel.state.threads[preview.parent_id],
|
|
505
|
+
])
|
|
506
|
+
: this.activeChannelMessagesSubject.next([...channel.state.messages]);
|
|
380
507
|
}
|
|
381
508
|
});
|
|
382
509
|
}
|
|
@@ -454,9 +581,15 @@ class ChannelService {
|
|
|
454
581
|
}
|
|
455
582
|
}
|
|
456
583
|
watchForActiveChannelEvents(channel) {
|
|
457
|
-
this.activeChannelSubscriptions.push(channel.on('message.new', () => {
|
|
584
|
+
this.activeChannelSubscriptions.push(channel.on('message.new', (event) => {
|
|
458
585
|
this.ngZone.run(() => {
|
|
459
|
-
|
|
586
|
+
event.message && event.message.parent_id
|
|
587
|
+
? this.activeThreadMessagesSubject.next([
|
|
588
|
+
...channel.state.threads[event.message.parent_id],
|
|
589
|
+
])
|
|
590
|
+
: this.activeChannelMessagesSubject.next([
|
|
591
|
+
...channel.state.messages,
|
|
592
|
+
]);
|
|
460
593
|
this.activeChannel$.pipe(first()).subscribe((c) => {
|
|
461
594
|
if (this.canSendReadEvents) {
|
|
462
595
|
void (c === null || c === void 0 ? void 0 : c.markRead());
|
|
@@ -485,19 +618,27 @@ class ChannelService {
|
|
|
485
618
|
}
|
|
486
619
|
messageUpdated(event) {
|
|
487
620
|
this.ngZone.run(() => {
|
|
488
|
-
const
|
|
621
|
+
const isThreadReply = event.message && event.message.parent_id;
|
|
622
|
+
const messages = isThreadReply
|
|
623
|
+
? this.activeThreadMessagesSubject.getValue()
|
|
624
|
+
: this.activeChannelMessagesSubject.getValue();
|
|
489
625
|
const messageIndex = messages.findIndex((m) => { var _a; return m.id === ((_a = event.message) === null || _a === void 0 ? void 0 : _a.id); });
|
|
490
626
|
if (messageIndex !== -1 && event.message) {
|
|
491
627
|
messages[messageIndex] = event.message;
|
|
492
|
-
|
|
628
|
+
isThreadReply
|
|
629
|
+
? this.activeThreadMessagesSubject.next([...messages])
|
|
630
|
+
: this.activeChannelMessagesSubject.next([...messages]);
|
|
493
631
|
}
|
|
494
632
|
});
|
|
495
633
|
}
|
|
496
634
|
messageReactionEventReceived(e) {
|
|
497
635
|
this.ngZone.run(() => {
|
|
498
636
|
var _a, _b, _c, _d;
|
|
637
|
+
const isThreadMessage = e.message && e.message.parent_id;
|
|
499
638
|
let messages;
|
|
500
|
-
|
|
639
|
+
(isThreadMessage
|
|
640
|
+
? this.activeThreadMessages$
|
|
641
|
+
: this.activeChannelMessages$)
|
|
501
642
|
.pipe(first())
|
|
502
643
|
.subscribe((m) => (messages = m));
|
|
503
644
|
const message = messages.find((m) => { var _a; return m.id === ((_a = e === null || e === void 0 ? void 0 : e.message) === null || _a === void 0 ? void 0 : _a.id); });
|
|
@@ -508,7 +649,9 @@ class ChannelService {
|
|
|
508
649
|
message.reaction_scores = Object.assign({}, (_b = e.message) === null || _b === void 0 ? void 0 : _b.reaction_scores);
|
|
509
650
|
message.latest_reactions = [...(((_c = e.message) === null || _c === void 0 ? void 0 : _c.latest_reactions) || [])];
|
|
510
651
|
message.own_reactions = [...(((_d = e.message) === null || _d === void 0 ? void 0 : _d.own_reactions) || [])];
|
|
511
|
-
|
|
652
|
+
isThreadMessage
|
|
653
|
+
? this.activeThreadMessagesSubject.next([...messages])
|
|
654
|
+
: this.activeChannelMessagesSubject.next([...messages]);
|
|
512
655
|
});
|
|
513
656
|
}
|
|
514
657
|
formatMessage(message) {
|
|
@@ -556,7 +699,7 @@ class ChannelService {
|
|
|
556
699
|
case 'message.new': {
|
|
557
700
|
this.ngZone.run(() => {
|
|
558
701
|
if (this.customNewMessageHandler) {
|
|
559
|
-
this.customNewMessageHandler(event, channel, this.channelListSetter, this.messageListSetter);
|
|
702
|
+
this.customNewMessageHandler(event, channel, this.channelListSetter, this.messageListSetter, this.threadListSetter, this.parentMessageSetter);
|
|
560
703
|
}
|
|
561
704
|
else {
|
|
562
705
|
this.handleNewMessage(event, channel);
|
|
@@ -567,7 +710,7 @@ class ChannelService {
|
|
|
567
710
|
case 'channel.hidden': {
|
|
568
711
|
this.ngZone.run(() => {
|
|
569
712
|
if (this.customChannelHiddenHandler) {
|
|
570
|
-
this.customChannelHiddenHandler(event, channel, this.channelListSetter, this.messageListSetter);
|
|
713
|
+
this.customChannelHiddenHandler(event, channel, this.channelListSetter, this.messageListSetter, this.threadListSetter, this.parentMessageSetter);
|
|
571
714
|
}
|
|
572
715
|
else {
|
|
573
716
|
this.handleChannelHidden(event);
|
|
@@ -578,7 +721,7 @@ class ChannelService {
|
|
|
578
721
|
case 'channel.deleted': {
|
|
579
722
|
this.ngZone.run(() => {
|
|
580
723
|
if (this.customChannelDeletedHandler) {
|
|
581
|
-
this.customChannelDeletedHandler(event, channel, this.channelListSetter, this.messageListSetter);
|
|
724
|
+
this.customChannelDeletedHandler(event, channel, this.channelListSetter, this.messageListSetter, this.threadListSetter, this.parentMessageSetter);
|
|
582
725
|
}
|
|
583
726
|
else {
|
|
584
727
|
this.handleChannelDeleted(event);
|
|
@@ -589,7 +732,7 @@ class ChannelService {
|
|
|
589
732
|
case 'channel.visible': {
|
|
590
733
|
this.ngZone.run(() => {
|
|
591
734
|
if (this.customChannelVisibleHandler) {
|
|
592
|
-
this.customChannelVisibleHandler(event, channel, this.channelListSetter, this.messageListSetter);
|
|
735
|
+
this.customChannelVisibleHandler(event, channel, this.channelListSetter, this.messageListSetter, this.threadListSetter, this.parentMessageSetter);
|
|
593
736
|
}
|
|
594
737
|
else {
|
|
595
738
|
this.handleChannelVisible(event, channel);
|
|
@@ -600,7 +743,7 @@ class ChannelService {
|
|
|
600
743
|
case 'channel.updated': {
|
|
601
744
|
this.ngZone.run(() => {
|
|
602
745
|
if (this.customChannelUpdatedHandler) {
|
|
603
|
-
this.customChannelUpdatedHandler(event, channel, this.channelListSetter, this.messageListSetter);
|
|
746
|
+
this.customChannelUpdatedHandler(event, channel, this.channelListSetter, this.messageListSetter, this.threadListSetter, this.parentMessageSetter);
|
|
604
747
|
}
|
|
605
748
|
else {
|
|
606
749
|
this.handleChannelUpdate(event);
|
|
@@ -611,7 +754,7 @@ class ChannelService {
|
|
|
611
754
|
case 'channel.truncated': {
|
|
612
755
|
this.ngZone.run(() => {
|
|
613
756
|
if (this.customChannelTruncatedHandler) {
|
|
614
|
-
this.customChannelTruncatedHandler(event, channel, this.channelListSetter, this.messageListSetter);
|
|
757
|
+
this.customChannelTruncatedHandler(event, channel, this.channelListSetter, this.messageListSetter, this.threadListSetter, this.parentMessageSetter);
|
|
615
758
|
}
|
|
616
759
|
else {
|
|
617
760
|
this.handleChannelTruncate(event);
|
|
@@ -651,6 +794,7 @@ class ChannelService {
|
|
|
651
794
|
}
|
|
652
795
|
}
|
|
653
796
|
}
|
|
797
|
+
// truncate active thread as well
|
|
654
798
|
handleChannelTruncate(event) {
|
|
655
799
|
var _a, _b;
|
|
656
800
|
const channelIndex = this.channels.findIndex((c) => c.cid === event.channel.cid);
|
|
@@ -662,6 +806,8 @@ class ChannelService {
|
|
|
662
806
|
channel.state.messages = [];
|
|
663
807
|
this.activeChannelSubject.next(channel);
|
|
664
808
|
this.activeChannelMessagesSubject.next([]);
|
|
809
|
+
this.activeParentMessageIdSubject.next(undefined);
|
|
810
|
+
this.activeThreadMessagesSubject.next([]);
|
|
665
811
|
}
|
|
666
812
|
}
|
|
667
813
|
}
|
|
@@ -677,6 +823,20 @@ class ChannelService {
|
|
|
677
823
|
const capabilites = (_a = channel.data) === null || _a === void 0 ? void 0 : _a.own_capabilities;
|
|
678
824
|
return capabilites.indexOf('read-events') !== -1;
|
|
679
825
|
}
|
|
826
|
+
transformToStreamMessage(message, channel) {
|
|
827
|
+
const isThreadMessage = !!message.parent_id;
|
|
828
|
+
if (this.isStreamMessage(message) &&
|
|
829
|
+
this.isFormatMessageResponse(message)) {
|
|
830
|
+
return message;
|
|
831
|
+
}
|
|
832
|
+
else if (this.isFormatMessageResponse(message)) {
|
|
833
|
+
return Object.assign(Object.assign({}, message), { readBy: isThreadMessage ? [] : getReadBy(message, channel) });
|
|
834
|
+
}
|
|
835
|
+
else {
|
|
836
|
+
const formatMessage = this.formatMessage(message);
|
|
837
|
+
return Object.assign(Object.assign({}, formatMessage), { readBy: isThreadMessage ? [] : getReadBy(formatMessage, channel) });
|
|
838
|
+
}
|
|
839
|
+
}
|
|
680
840
|
}
|
|
681
841
|
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 });
|
|
682
842
|
ChannelService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: ChannelService, providedIn: 'root' });
|
|
@@ -989,6 +1149,7 @@ const en = {
|
|
|
989
1149
|
Flag: 'Flag',
|
|
990
1150
|
'Message Failed': 'Message Failed',
|
|
991
1151
|
'Message Failed · Unauthorized': 'Message Failed · Unauthorized',
|
|
1152
|
+
'Message Failed · Click to try again': 'Message Failed · Click to try again',
|
|
992
1153
|
'Message deleted': 'Message deleted',
|
|
993
1154
|
'Message has been successfully flagged': 'Message has been successfully flagged',
|
|
994
1155
|
'Message pinned': 'Message pinned',
|
|
@@ -1039,6 +1200,7 @@ const en = {
|
|
|
1039
1200
|
test: 'success',
|
|
1040
1201
|
'Sending links is not allowed in this conversation': 'Sending links is not allowed in this conversation',
|
|
1041
1202
|
"You can't send messages in this channel": "You can't send messages in this channel",
|
|
1203
|
+
"You can't send thread replies in this channel": "You can't send thread replies in this channel",
|
|
1042
1204
|
'Unsupported file type: {{type}}': 'Unsupported file type: {{type}}',
|
|
1043
1205
|
},
|
|
1044
1206
|
};
|
|
@@ -1054,14 +1216,14 @@ class StreamI18nService {
|
|
|
1054
1216
|
this.translteService.setTranslation(lang, { streamChat: Object.assign(Object.assign({}, en.streamChat), overrides) }, true);
|
|
1055
1217
|
}
|
|
1056
1218
|
}
|
|
1057
|
-
StreamI18nService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: StreamI18nService, deps: [{ token:
|
|
1219
|
+
StreamI18nService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: StreamI18nService, deps: [{ token: i1.TranslateService }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
1058
1220
|
StreamI18nService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: StreamI18nService, providedIn: 'root' });
|
|
1059
1221
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: StreamI18nService, decorators: [{
|
|
1060
1222
|
type: Injectable,
|
|
1061
1223
|
args: [{
|
|
1062
1224
|
providedIn: 'root',
|
|
1063
1225
|
}]
|
|
1064
|
-
}], ctorParameters: function () { return [{ type:
|
|
1226
|
+
}], ctorParameters: function () { return [{ type: i1.TranslateService }]; } });
|
|
1065
1227
|
|
|
1066
1228
|
class AvatarComponent {
|
|
1067
1229
|
constructor() {
|
|
@@ -1075,7 +1237,7 @@ class AvatarComponent {
|
|
|
1075
1237
|
}
|
|
1076
1238
|
}
|
|
1077
1239
|
AvatarComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: AvatarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1078
|
-
AvatarComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.5", type: AvatarComponent, selector: "stream-avatar", inputs: { name: "name", imageUrl: "imageUrl", size: "size" }, ngImport: i0, template: "<div\n class=\"str-chat__avatar str-chat__avatar--circle\"\n title=\"{{ name }}\"\n [style]=\"{\n flexBasis: size + 'px',\n fontSize: size / 2 + 'px',\n height: size + 'px',\n lineHeight: size + 'px',\n width: size + 'px'\n }\"\n>\n <img\n *ngIf=\"imageUrl && !isError; else fallback\"\n class=\"str-chat__avatar-image str-chat__avatar-image{{\n isLoaded ? ' str-chat__avatar-image--loaded' : ''\n }}\"\n src=\"{{ imageUrl }}\"\n alt=\"{{ initials }}\"\n data-testid=\"avatar-img\"\n (load)=\"isLoaded = true\"\n (error)=\"isError = true\"\n [style]=\"{\n flexBasis: size + 'px',\n height: size + 'px',\n objectFit: 'cover',\n width: size + 'px'\n }\"\n />\n <ng-template #fallback>\n <div data-testid=\"fallback-img\" class=\"str-chat__avatar-fallback\">\n {{ initials }}\n </div>\n </ng-template>\n</div>\n", styles: [""], directives: [{ type:
|
|
1240
|
+
AvatarComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.5", type: AvatarComponent, selector: "stream-avatar", inputs: { name: "name", imageUrl: "imageUrl", size: "size" }, ngImport: i0, template: "<div\n class=\"str-chat__avatar str-chat__avatar--circle\"\n title=\"{{ name }}\"\n [style]=\"{\n flexBasis: size + 'px',\n fontSize: size / 2 + 'px',\n height: size + 'px',\n lineHeight: size + 'px',\n width: size + 'px'\n }\"\n>\n <img\n *ngIf=\"imageUrl && !isError; else fallback\"\n class=\"str-chat__avatar-image str-chat__avatar-image{{\n isLoaded ? ' str-chat__avatar-image--loaded' : ''\n }}\"\n src=\"{{ imageUrl }}\"\n alt=\"{{ initials }}\"\n data-testid=\"avatar-img\"\n (load)=\"isLoaded = true\"\n (error)=\"isError = true\"\n [style]=\"{\n flexBasis: size + 'px',\n height: size + 'px',\n objectFit: 'cover',\n width: size + 'px'\n }\"\n />\n <ng-template #fallback>\n <div data-testid=\"fallback-img\" class=\"str-chat__avatar-fallback\">\n {{ initials }}\n </div>\n </ng-template>\n</div>\n", styles: [""], directives: [{ type: i6.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }] });
|
|
1079
1241
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: AvatarComponent, decorators: [{
|
|
1080
1242
|
type: Component,
|
|
1081
1243
|
args: [{
|
|
@@ -1095,7 +1257,7 @@ class IconComponent {
|
|
|
1095
1257
|
constructor() { }
|
|
1096
1258
|
}
|
|
1097
1259
|
IconComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: IconComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1098
|
-
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", directives: [{ type:
|
|
1260
|
+
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: i1.TranslateDirective, selector: "[translate],[ngx-translate]", inputs: ["translate", "translateParams"] }] });
|
|
1099
1261
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: IconComponent, decorators: [{
|
|
1100
1262
|
type: Component,
|
|
1101
1263
|
args: [{
|
|
@@ -1116,7 +1278,7 @@ class LoadingIndicatorComponent {
|
|
|
1116
1278
|
}
|
|
1117
1279
|
}
|
|
1118
1280
|
LoadingIndicatorComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: LoadingIndicatorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1119
|
-
LoadingIndicatorComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.5", type: LoadingIndicatorComponent, selector: "stream-loading-indicator", inputs: { size: "size", color: "color" }, ngImport: i0, template: "<div class=\"str-chat__loading-indicator\">\n <svg\n [attr.height]=\"size\"\n viewBox=\"0 0 30 30\"\n [attr.width]=\"size\"\n data-testid=\"loading-indicator\"\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <defs>\n <linearGradient id=\"a\" x1=\"50%\" x2=\"50%\" y1=\"0%\" y2=\"100%\">\n <stop offset=\"0%\" stop-color=\"#FFF\" stop-opacity=\"0\" />\n <stop\n data-testid=\"stop-color\"\n offset=\"100%\"\n [attr.stop-color]=\"color\"\n stop-opacity=\"1\"\n [ngStyle]=\"{ stopColor: color }\"\n />\n </linearGradient>\n </defs>\n <path\n d=\"M2.518 23.321l1.664-1.11A12.988 12.988 0 0 0 15 28c7.18 0 13-5.82 13-13S22.18 2 15 2V0c8.284 0 15 6.716 15 15 0 8.284-6.716 15-15 15-5.206 0-9.792-2.652-12.482-6.679z\"\n fill=\"url(#a)\"\n fillRule=\"evenodd\"\n />\n </svg>\n</div>\n", directives: [{ type:
|
|
1281
|
+
LoadingIndicatorComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.5", type: LoadingIndicatorComponent, selector: "stream-loading-indicator", inputs: { size: "size", color: "color" }, ngImport: i0, template: "<div class=\"str-chat__loading-indicator\">\n <svg\n [attr.height]=\"size\"\n viewBox=\"0 0 30 30\"\n [attr.width]=\"size\"\n data-testid=\"loading-indicator\"\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <defs>\n <linearGradient id=\"a\" x1=\"50%\" x2=\"50%\" y1=\"0%\" y2=\"100%\">\n <stop offset=\"0%\" stop-color=\"#FFF\" stop-opacity=\"0\" />\n <stop\n data-testid=\"stop-color\"\n offset=\"100%\"\n [attr.stop-color]=\"color\"\n stop-opacity=\"1\"\n [ngStyle]=\"{ stopColor: color }\"\n />\n </linearGradient>\n </defs>\n <path\n d=\"M2.518 23.321l1.664-1.11A12.988 12.988 0 0 0 15 28c7.18 0 13-5.82 13-13S22.18 2 15 2V0c8.284 0 15 6.716 15 15 0 8.284-6.716 15-15 15-5.206 0-9.792-2.652-12.482-6.679z\"\n fill=\"url(#a)\"\n fillRule=\"evenodd\"\n />\n </svg>\n</div>\n", directives: [{ type: i6.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }] });
|
|
1120
1282
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: LoadingIndicatorComponent, decorators: [{
|
|
1121
1283
|
type: Component,
|
|
1122
1284
|
args: [{
|
|
@@ -1158,6 +1320,8 @@ class TextareaDirective {
|
|
|
1158
1320
|
this.componentRef.instance.areMentionsEnabled = this.areMentionsEnabled;
|
|
1159
1321
|
this.componentRef.instance.mentionAutocompleteItemTemplate =
|
|
1160
1322
|
this.mentionAutocompleteItemTemplate;
|
|
1323
|
+
this.componentRef.instance.commandAutocompleteItemTemplate =
|
|
1324
|
+
this.commandAutocompleteItemTemplate;
|
|
1161
1325
|
this.componentRef.instance.mentionScope = this.mentionScope;
|
|
1162
1326
|
this.componentRef.instance.value = this.value;
|
|
1163
1327
|
}
|
|
@@ -1169,6 +1333,10 @@ class TextareaDirective {
|
|
|
1169
1333
|
this.componentRef.instance.mentionAutocompleteItemTemplate =
|
|
1170
1334
|
this.mentionAutocompleteItemTemplate;
|
|
1171
1335
|
}
|
|
1336
|
+
if (changes.commandAutocompleteItemTemplate) {
|
|
1337
|
+
this.componentRef.instance.commandAutocompleteItemTemplate =
|
|
1338
|
+
this.commandAutocompleteItemTemplate;
|
|
1339
|
+
}
|
|
1172
1340
|
if (changes.mentionScope) {
|
|
1173
1341
|
this.componentRef.instance.mentionScope = this.mentionScope;
|
|
1174
1342
|
}
|
|
@@ -1184,7 +1352,7 @@ class TextareaDirective {
|
|
|
1184
1352
|
}
|
|
1185
1353
|
}
|
|
1186
1354
|
TextareaDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: TextareaDirective, deps: [{ token: i0.ViewContainerRef }], target: i0.ɵɵFactoryTarget.Directive });
|
|
1187
|
-
TextareaDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "12.2.5", type: TextareaDirective, selector: "[streamTextarea]", inputs: { componentRef: "componentRef", areMentionsEnabled: "areMentionsEnabled", mentionAutocompleteItemTemplate: "mentionAutocompleteItemTemplate", mentionScope: "mentionScope", value: "value" }, outputs: { valueChange: "valueChange", send: "send", userMentions: "userMentions" }, usesOnChanges: true, ngImport: i0 });
|
|
1355
|
+
TextareaDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "12.2.5", type: TextareaDirective, selector: "[streamTextarea]", inputs: { componentRef: "componentRef", areMentionsEnabled: "areMentionsEnabled", mentionAutocompleteItemTemplate: "mentionAutocompleteItemTemplate", mentionScope: "mentionScope", commandAutocompleteItemTemplate: "commandAutocompleteItemTemplate", value: "value" }, outputs: { valueChange: "valueChange", send: "send", userMentions: "userMentions" }, usesOnChanges: true, ngImport: i0 });
|
|
1188
1356
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: TextareaDirective, decorators: [{
|
|
1189
1357
|
type: Directive,
|
|
1190
1358
|
args: [{
|
|
@@ -1198,6 +1366,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImpor
|
|
|
1198
1366
|
type: Input
|
|
1199
1367
|
}], mentionScope: [{
|
|
1200
1368
|
type: Input
|
|
1369
|
+
}], commandAutocompleteItemTemplate: [{
|
|
1370
|
+
type: Input
|
|
1201
1371
|
}], value: [{
|
|
1202
1372
|
type: Input
|
|
1203
1373
|
}], valueChange: [{
|
|
@@ -1225,6 +1395,90 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImpor
|
|
|
1225
1395
|
}]
|
|
1226
1396
|
}], ctorParameters: function () { return []; } });
|
|
1227
1397
|
|
|
1398
|
+
class ImageLoadService {
|
|
1399
|
+
constructor() {
|
|
1400
|
+
this.imageLoad$ = new Subject();
|
|
1401
|
+
}
|
|
1402
|
+
}
|
|
1403
|
+
ImageLoadService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: ImageLoadService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
1404
|
+
ImageLoadService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: ImageLoadService, providedIn: 'root' });
|
|
1405
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: ImageLoadService, decorators: [{
|
|
1406
|
+
type: Injectable,
|
|
1407
|
+
args: [{
|
|
1408
|
+
providedIn: 'root',
|
|
1409
|
+
}]
|
|
1410
|
+
}], ctorParameters: function () { return []; } });
|
|
1411
|
+
|
|
1412
|
+
class AttachmentListComponent {
|
|
1413
|
+
constructor(imageLoadService, channelService) {
|
|
1414
|
+
this.imageLoadService = imageLoadService;
|
|
1415
|
+
this.channelService = channelService;
|
|
1416
|
+
this.attachments = [];
|
|
1417
|
+
this.orderedAttachments = [];
|
|
1418
|
+
}
|
|
1419
|
+
ngOnChanges() {
|
|
1420
|
+
this.orderedAttachments = [
|
|
1421
|
+
...this.attachments.filter((a) => this.isImage(a)),
|
|
1422
|
+
...this.attachments.filter((a) => this.isFile(a)),
|
|
1423
|
+
...this.attachments.filter((a) => this.isCard(a)),
|
|
1424
|
+
];
|
|
1425
|
+
}
|
|
1426
|
+
trackById(index) {
|
|
1427
|
+
return index;
|
|
1428
|
+
}
|
|
1429
|
+
isImage(attachment) {
|
|
1430
|
+
return isImageAttachment(attachment);
|
|
1431
|
+
}
|
|
1432
|
+
isFile(attachment) {
|
|
1433
|
+
return attachment.type === 'file';
|
|
1434
|
+
}
|
|
1435
|
+
isCard(attachment) {
|
|
1436
|
+
return (!attachment.type ||
|
|
1437
|
+
(attachment.type === 'image' && !this.isImage(attachment)) ||
|
|
1438
|
+
attachment.type === 'giphy');
|
|
1439
|
+
}
|
|
1440
|
+
imageLoaded() {
|
|
1441
|
+
this.imageLoadService.imageLoad$.next();
|
|
1442
|
+
}
|
|
1443
|
+
hasFileSize(attachment) {
|
|
1444
|
+
return (attachment.file_size && Number.isFinite(Number(attachment.file_size)));
|
|
1445
|
+
}
|
|
1446
|
+
getFileSize(attachment) {
|
|
1447
|
+
return prettybytes(attachment.file_size);
|
|
1448
|
+
}
|
|
1449
|
+
trimUrl(url) {
|
|
1450
|
+
if (url !== undefined && url !== null) {
|
|
1451
|
+
const [trimmedUrl] = url
|
|
1452
|
+
.replace(/^(?:https?:\/\/)?(?:www\.)?/i, '')
|
|
1453
|
+
.split('/');
|
|
1454
|
+
return trimmedUrl;
|
|
1455
|
+
}
|
|
1456
|
+
return null;
|
|
1457
|
+
}
|
|
1458
|
+
sendAction(action) {
|
|
1459
|
+
void this.channelService.sendAction(this.messageId, {
|
|
1460
|
+
[action.name]: action.value,
|
|
1461
|
+
});
|
|
1462
|
+
}
|
|
1463
|
+
trackByActionValue(_, item) {
|
|
1464
|
+
return item.value;
|
|
1465
|
+
}
|
|
1466
|
+
}
|
|
1467
|
+
AttachmentListComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: AttachmentListComponent, deps: [{ token: ImageLoadService }, { token: ChannelService }], target: i0.ɵɵFactoryTarget.Component });
|
|
1468
|
+
AttachmentListComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.5", type: AttachmentListComponent, selector: "stream-attachment-list", inputs: { messageId: "messageId", attachments: "attachments" }, usesOnChanges: true, ngImport: i0, template: "<ng-container *ngFor=\"let attachment of orderedAttachments; trackBy: trackById\">\n <div\n data-testclass=\"attachment-container\"\n class=\"str-chat__message-attachment str-chat__message-attachment--{{\n attachment.type\n }}\"\n [class.str-chat__message-attachment--card]=\"isCard(attachment)\"\n [class.str-chat-angular__message-attachment-file-single]=\"\n isFile(attachment)\n \"\n >\n <img\n *ngIf=\"isImage(attachment)\"\n class=\"str-chat__message-attachment--img\"\n data-testclass=\"image\"\n [src]=\"attachment.img_url || attachment.thumb_url || attachment.image_url\"\n [alt]=\"attachment?.fallback\"\n (load)=\"imageLoaded()\"\n />\n <div\n *ngIf=\"isFile(attachment)\"\n class=\"\n str-chat__message-attachment-file--item\n str-chat-angular__message-attachment-file-single\n \"\n >\n <stream-icon icon=\"file\" [size]=\"30\"></stream-icon>\n <div class=\"str-chat__message-attachment-file--item-text\">\n <a\n data-testclass=\"file-link\"\n download\n href=\"{{ attachment.asset_url }}\"\n target=\"_blank\"\n >\n {{ attachment.title }}\n </a>\n <span data-testclass=\"size\" *ngIf=\"hasFileSize(attachment)\">{{\n getFileSize(attachment)\n }}</span>\n </div>\n </div>\n <div\n *ngIf=\"isCard(attachment)\"\n class=\"str-chat__message-attachment-card str-chat__message-attachment-card--{{\n attachment.type\n }}\"\n >\n <div\n *ngIf=\"attachment.image_url || attachment.thumb_url\"\n class=\"str-chat__message-attachment-card--header\"\n >\n <img\n data-testclass=\"card-img\"\n alt=\"{{ attachment.image_url || attachment.thumb_url }}\"\n src=\"{{ attachment.image_url || attachment.thumb_url }}\"\n />\n </div>\n <div class=\"str-chat__message-attachment-card--content\">\n <div class=\"str-chat__message-attachment-card--flex\">\n <div\n *ngIf=\"attachment.title\"\n data-testclass=\"card-title\"\n class=\"str-chat__message-attachment-card--title\"\n >\n {{ attachment.title }}\n </div>\n <div\n *ngIf=\"attachment.text\"\n class=\"str-chat__message-attachment-card--text\"\n data-testclass=\"card-text\"\n >\n {{ attachment.text }}\n </div>\n <a\n class=\"str-chat__message-attachment-card--url\"\n *ngIf=\"attachment.title_link || attachment.og_scrape_url\"\n data-testclass=\"url-link\"\n noopener\n noreferrer\n href=\"{{ attachment.title_link || attachment.og_scrape_url }}\"\n target=\"_blank\"\n >\n {{ trimUrl(attachment.title_link || attachment.og_scrape_url) }}\n </a>\n </div>\n </div>\n </div>\n <div\n class=\"str-chat__message-attachment-actions\"\n *ngIf=\"attachment.actions && attachment.actions.length > 0\"\n >\n <div class=\"str-chat__message-attachment-actions-form\">\n <button\n *ngFor=\"let action of attachment.actions; trackBy: trackByActionValue\"\n class=\"str-chat__message-attachment-actions-button str-chat__message-attachment-actions-button--{{\n action.style\n }}\"\n data-testclass=\"attachment-action\"\n (click)=\"sendAction(action)\"\n (keyup.enter)=\"sendAction(action)\"\n >\n {{ action.text }}\n </button>\n </div>\n </div>\n </div>\n</ng-container>\n", components: [{ type: IconComponent, selector: "stream-icon", inputs: ["icon", "size"] }], directives: [{ type: i6.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i6.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }] });
|
|
1469
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: AttachmentListComponent, decorators: [{
|
|
1470
|
+
type: Component,
|
|
1471
|
+
args: [{
|
|
1472
|
+
selector: 'stream-attachment-list',
|
|
1473
|
+
templateUrl: './attachment-list.component.html',
|
|
1474
|
+
styles: [],
|
|
1475
|
+
}]
|
|
1476
|
+
}], ctorParameters: function () { return [{ type: ImageLoadService }, { type: ChannelService }]; }, propDecorators: { messageId: [{
|
|
1477
|
+
type: Input
|
|
1478
|
+
}], attachments: [{
|
|
1479
|
+
type: Input
|
|
1480
|
+
}] } });
|
|
1481
|
+
|
|
1228
1482
|
class AttachmentPreviewListComponent {
|
|
1229
1483
|
constructor(attachmentService) {
|
|
1230
1484
|
this.attachmentService = attachmentService;
|
|
@@ -1245,7 +1499,7 @@ class AttachmentPreviewListComponent {
|
|
|
1245
1499
|
}
|
|
1246
1500
|
}
|
|
1247
1501
|
AttachmentPreviewListComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: AttachmentPreviewListComponent, deps: [{ token: AttachmentService }], target: i0.ɵɵFactoryTarget.Component });
|
|
1248
|
-
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:
|
|
1502
|
+
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: i1.TranslateDirective, selector: "[translate],[ngx-translate]", inputs: ["translate", "translateParams"] }], pipes: { "async": i6.AsyncPipe } });
|
|
1249
1503
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: AttachmentPreviewListComponent, decorators: [{
|
|
1250
1504
|
type: Component,
|
|
1251
1505
|
args: [{
|
|
@@ -1265,6 +1519,7 @@ class MessageInputComponent {
|
|
|
1265
1519
|
this.componentFactoryResolver = componentFactoryResolver;
|
|
1266
1520
|
this.cdRef = cdRef;
|
|
1267
1521
|
this.chatClient = chatClient;
|
|
1522
|
+
this.mode = 'main';
|
|
1268
1523
|
this.messageUpdate = new EventEmitter();
|
|
1269
1524
|
this.textareaValue = '';
|
|
1270
1525
|
this.mentionedUsers = [];
|
|
@@ -1285,14 +1540,19 @@ class MessageInputComponent {
|
|
|
1285
1540
|
this.isFileUploadAuthorized =
|
|
1286
1541
|
capabilities.indexOf('upload-file') !== -1;
|
|
1287
1542
|
this.canSendLinks = capabilities.indexOf('send-links') !== -1;
|
|
1288
|
-
this.
|
|
1289
|
-
|
|
1290
|
-
this.cdRef.detectChanges();
|
|
1291
|
-
this.initTextarea();
|
|
1292
|
-
}
|
|
1543
|
+
this.channel = channel;
|
|
1544
|
+
this.setCanSendMessages();
|
|
1293
1545
|
}
|
|
1294
1546
|
}));
|
|
1295
1547
|
this.subscriptions.push(this.chatClient.appSettings$.subscribe((appSettings) => (this.appSettings = appSettings)));
|
|
1548
|
+
this.subscriptions.push(this.channelService.messageToQuote$.subscribe((m) => {
|
|
1549
|
+
const isThreadReply = m && m.parent_id;
|
|
1550
|
+
if ((this.mode === 'thread' && isThreadReply) ||
|
|
1551
|
+
(this.mode === 'thread' && this.quotedMessage && !m) ||
|
|
1552
|
+
(this.mode === 'main' && !isThreadReply)) {
|
|
1553
|
+
this.quotedMessage = m;
|
|
1554
|
+
}
|
|
1555
|
+
}));
|
|
1296
1556
|
this.attachmentUploads$ = this.attachmentService.attachmentUploads$;
|
|
1297
1557
|
this.isFileUploadEnabled = this.configService.isFileUploadEnabled;
|
|
1298
1558
|
this.acceptedFileTypes = this.configService.acceptedFileTypes;
|
|
@@ -1302,6 +1562,8 @@ class MessageInputComponent {
|
|
|
1302
1562
|
this.mentionAutocompleteItemTemplate =
|
|
1303
1563
|
this.configService.mentionAutocompleteItemTemplate;
|
|
1304
1564
|
this.mentionScope = this.configService.mentionScope;
|
|
1565
|
+
this.commandAutocompleteItemTemplate =
|
|
1566
|
+
this.configService.commandAutocompleteItemTemplate;
|
|
1305
1567
|
}
|
|
1306
1568
|
ngAfterViewInit() {
|
|
1307
1569
|
this.isViewInited = true;
|
|
@@ -1332,14 +1594,22 @@ class MessageInputComponent {
|
|
|
1332
1594
|
this.configService.mentionAutocompleteItemTemplate =
|
|
1333
1595
|
this.mentionAutocompleteItemTemplate;
|
|
1334
1596
|
}
|
|
1597
|
+
if (changes.commandAutocompleteItemTemplate) {
|
|
1598
|
+
this.configService.commandAutocompleteItemTemplate =
|
|
1599
|
+
this.commandAutocompleteItemTemplate;
|
|
1600
|
+
}
|
|
1335
1601
|
if (changes.mentionScope) {
|
|
1336
1602
|
this.configService.mentionScope = this.mentionScope;
|
|
1337
1603
|
}
|
|
1604
|
+
if (changes.mode) {
|
|
1605
|
+
this.setCanSendMessages();
|
|
1606
|
+
}
|
|
1338
1607
|
}
|
|
1339
1608
|
ngOnDestroy() {
|
|
1340
1609
|
this.subscriptions.forEach((s) => s.unsubscribe());
|
|
1341
1610
|
}
|
|
1342
1611
|
messageSent() {
|
|
1612
|
+
var _a;
|
|
1343
1613
|
return __awaiter(this, void 0, void 0, function* () {
|
|
1344
1614
|
let attachmentUploadInProgressCounter;
|
|
1345
1615
|
this.attachmentService.attachmentUploadInProgressCounter$
|
|
@@ -1364,10 +1634,16 @@ class MessageInputComponent {
|
|
|
1364
1634
|
if (!this.isUpdate) {
|
|
1365
1635
|
this.textareaValue = '';
|
|
1366
1636
|
}
|
|
1637
|
+
let parentMessageId = undefined;
|
|
1638
|
+
if (this.mode === 'thread') {
|
|
1639
|
+
this.channelService.activeParentMessageId$
|
|
1640
|
+
.pipe(first())
|
|
1641
|
+
.subscribe((id) => (parentMessageId = id));
|
|
1642
|
+
}
|
|
1367
1643
|
try {
|
|
1368
1644
|
yield (this.isUpdate
|
|
1369
1645
|
? this.channelService.updateMessage(Object.assign(Object.assign({}, this.message), { text: text, attachments: attachments }))
|
|
1370
|
-
: this.channelService.sendMessage(text, attachments, this.mentionedUsers));
|
|
1646
|
+
: this.channelService.sendMessage(text, attachments, this.mentionedUsers, parentMessageId, (_a = this.quotedMessage) === null || _a === void 0 ? void 0 : _a.id));
|
|
1371
1647
|
this.messageUpdate.emit();
|
|
1372
1648
|
if (!this.isUpdate) {
|
|
1373
1649
|
this.attachmentService.resetAttachmentUploads();
|
|
@@ -1378,6 +1654,9 @@ class MessageInputComponent {
|
|
|
1378
1654
|
this.notificationService.addTemporaryNotification('streamChat.Edit message request failed');
|
|
1379
1655
|
}
|
|
1380
1656
|
}
|
|
1657
|
+
if (this.quotedMessage) {
|
|
1658
|
+
this.deselectMessageToQuote();
|
|
1659
|
+
}
|
|
1381
1660
|
});
|
|
1382
1661
|
}
|
|
1383
1662
|
get containsLinks() {
|
|
@@ -1387,6 +1666,13 @@ class MessageInputComponent {
|
|
|
1387
1666
|
var _a;
|
|
1388
1667
|
return this.acceptedFileTypes ? (_a = this.acceptedFileTypes) === null || _a === void 0 ? void 0 : _a.join(',') : '';
|
|
1389
1668
|
}
|
|
1669
|
+
get quotedMessageAttachments() {
|
|
1670
|
+
var _a;
|
|
1671
|
+
const originalAttachments = (_a = this.quotedMessage) === null || _a === void 0 ? void 0 : _a.attachments;
|
|
1672
|
+
return originalAttachments && originalAttachments.length
|
|
1673
|
+
? [originalAttachments[0]]
|
|
1674
|
+
: [];
|
|
1675
|
+
}
|
|
1390
1676
|
filesSelected(fileList) {
|
|
1391
1677
|
return __awaiter(this, void 0, void 0, function* () {
|
|
1392
1678
|
if (!(yield this.areAttachemntsValid(fileList))) {
|
|
@@ -1396,6 +1682,9 @@ class MessageInputComponent {
|
|
|
1396
1682
|
this.clearFileInput();
|
|
1397
1683
|
});
|
|
1398
1684
|
}
|
|
1685
|
+
deselectMessageToQuote() {
|
|
1686
|
+
this.channelService.selectMessageToQuote(undefined);
|
|
1687
|
+
}
|
|
1399
1688
|
clearFileInput() {
|
|
1400
1689
|
this.fileInput.nativeElement.value = '';
|
|
1401
1690
|
}
|
|
@@ -1461,9 +1750,24 @@ class MessageInputComponent {
|
|
|
1461
1750
|
return isValid;
|
|
1462
1751
|
});
|
|
1463
1752
|
}
|
|
1753
|
+
setCanSendMessages() {
|
|
1754
|
+
var _a, _b;
|
|
1755
|
+
const capabilities = (_b = (_a = this.channel) === null || _a === void 0 ? void 0 : _a.data) === null || _b === void 0 ? void 0 : _b.own_capabilities;
|
|
1756
|
+
if (!capabilities) {
|
|
1757
|
+
this.canSendMessages = false;
|
|
1758
|
+
}
|
|
1759
|
+
else {
|
|
1760
|
+
this.canSendMessages =
|
|
1761
|
+
capabilities.indexOf(this.mode === 'main' ? 'send-message' : 'send-reply') !== -1;
|
|
1762
|
+
}
|
|
1763
|
+
if (this.isViewInited) {
|
|
1764
|
+
this.cdRef.detectChanges();
|
|
1765
|
+
this.initTextarea();
|
|
1766
|
+
}
|
|
1767
|
+
}
|
|
1464
1768
|
}
|
|
1465
1769
|
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 });
|
|
1466
|
-
MessageInputComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.5", type: MessageInputComponent, selector: "stream-message-input", inputs: { isFileUploadEnabled: "isFileUploadEnabled", areMentionsEnabled: "areMentionsEnabled", mentionScope: "mentionScope", mentionAutocompleteItemTemplate: "mentionAutocompleteItemTemplate", acceptedFileTypes: "acceptedFileTypes", isMultipleFileUploadEnabled: "isMultipleFileUploadEnabled", message: "message" }, outputs: { messageUpdate: "messageUpdate" }, providers: [AttachmentService], viewQueries: [{ propertyName: "fileInput", first: true, predicate: ["fileInput"], descendants: true }, { propertyName: "textareaAnchor", first: true, predicate: TextareaDirective, descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div\n class=\"str-chat__input-flat\"\n [class.str-chat__input-flat-has-attachments]=\"\n (attachmentUploads$ | async)!.length > 0\n \"\n>\n <div class=\"str-chat__input-flat-wrapper\">\n <div
|
|
1770
|
+
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": i1.TranslatePipe } });
|
|
1467
1771
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: MessageInputComponent, decorators: [{
|
|
1468
1772
|
type: Component,
|
|
1469
1773
|
args: [{
|
|
@@ -1483,6 +1787,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImpor
|
|
|
1483
1787
|
type: Input
|
|
1484
1788
|
}], mentionAutocompleteItemTemplate: [{
|
|
1485
1789
|
type: Input
|
|
1790
|
+
}], commandAutocompleteItemTemplate: [{
|
|
1791
|
+
type: Input
|
|
1792
|
+
}], mode: [{
|
|
1793
|
+
type: Input
|
|
1486
1794
|
}], acceptedFileTypes: [{
|
|
1487
1795
|
type: Input
|
|
1488
1796
|
}], isMultipleFileUploadEnabled: [{
|
|
@@ -1541,7 +1849,7 @@ class ModalComponent {
|
|
|
1541
1849
|
}
|
|
1542
1850
|
}
|
|
1543
1851
|
ModalComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: ModalComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1544
|
-
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:
|
|
1852
|
+
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: i1.TranslateDirective, selector: "[translate],[ngx-translate]", inputs: ["translate", "translateParams"] }] });
|
|
1545
1853
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: ModalComponent, decorators: [{
|
|
1546
1854
|
type: Component,
|
|
1547
1855
|
args: [{
|
|
@@ -1584,7 +1892,7 @@ class NotificationListComponent {
|
|
|
1584
1892
|
}
|
|
1585
1893
|
}
|
|
1586
1894
|
NotificationListComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: NotificationListComponent, deps: [{ token: NotificationService }], target: i0.ɵɵFactoryTarget.Component });
|
|
1587
|
-
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:
|
|
1895
|
+
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": i1.TranslatePipe } });
|
|
1588
1896
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: NotificationListComponent, decorators: [{
|
|
1589
1897
|
type: Component,
|
|
1590
1898
|
args: [{
|
|
@@ -1635,21 +1943,32 @@ class MessageActionsBoxComponent {
|
|
|
1635
1943
|
}
|
|
1636
1944
|
}
|
|
1637
1945
|
get isQuoteVisible() {
|
|
1638
|
-
|
|
1946
|
+
var _a;
|
|
1947
|
+
return ((this.enabledActions.indexOf('quote') !== -1 ||
|
|
1948
|
+
this.enabledActions.indexOf('quote-message') !== -1) &&
|
|
1949
|
+
!((_a = this.message) === null || _a === void 0 ? void 0 : _a.quoted_message));
|
|
1639
1950
|
}
|
|
1640
1951
|
get isEditVisible() {
|
|
1641
|
-
return ((this.enabledActions.indexOf('edit') !== -1
|
|
1642
|
-
this.enabledActions.indexOf('
|
|
1952
|
+
return (((this.enabledActions.indexOf('edit') !== -1 ||
|
|
1953
|
+
this.enabledActions.indexOf('update-own-message') !== -1) &&
|
|
1954
|
+
this.isMine) ||
|
|
1955
|
+
this.enabledActions.indexOf('edit-any') !== -1 ||
|
|
1956
|
+
this.enabledActions.indexOf('update-any-message') !== -1);
|
|
1643
1957
|
}
|
|
1644
1958
|
get isDeleteVisible() {
|
|
1645
|
-
return ((this.enabledActions.indexOf('delete') !== -1
|
|
1646
|
-
this.enabledActions.indexOf('delete-
|
|
1959
|
+
return (((this.enabledActions.indexOf('delete') !== -1 ||
|
|
1960
|
+
this.enabledActions.indexOf('delete-own-message') !== -1) &&
|
|
1961
|
+
this.isMine) ||
|
|
1962
|
+
this.enabledActions.indexOf('delete-any') !== -1 ||
|
|
1963
|
+
this.enabledActions.indexOf('delete-any-message') !== -1);
|
|
1647
1964
|
}
|
|
1648
1965
|
get isMuteVisible() {
|
|
1649
1966
|
return this.enabledActions.indexOf('mute') !== -1;
|
|
1650
1967
|
}
|
|
1651
1968
|
get isFlagVisible() {
|
|
1652
|
-
return this.enabledActions.indexOf('flag') !== -1
|
|
1969
|
+
return ((this.enabledActions.indexOf('flag') !== -1 ||
|
|
1970
|
+
this.enabledActions.indexOf('flag-message') !== -1) &&
|
|
1971
|
+
!this.isMine);
|
|
1653
1972
|
}
|
|
1654
1973
|
get isPinVisible() {
|
|
1655
1974
|
return this.enabledActions.indexOf('pin') !== -1;
|
|
@@ -1672,7 +1991,7 @@ class MessageActionsBoxComponent {
|
|
|
1672
1991
|
alert('Feature not yet implemented');
|
|
1673
1992
|
}
|
|
1674
1993
|
quoteClicked() {
|
|
1675
|
-
|
|
1994
|
+
this.channelService.selectMessageToQuote(this.message);
|
|
1676
1995
|
}
|
|
1677
1996
|
editClicked() {
|
|
1678
1997
|
this.isEditing.emit(true);
|
|
@@ -1694,7 +2013,7 @@ class MessageActionsBoxComponent {
|
|
|
1694
2013
|
}
|
|
1695
2014
|
}
|
|
1696
2015
|
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 });
|
|
1697
|
-
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", "acceptedFileTypes", "isMultipleFileUploadEnabled", "message"], outputs: ["messageUpdate"] }, { type: NotificationListComponent, selector: "stream-notification-list" }], directives: [{ type:
|
|
2016
|
+
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: i1.TranslateDirective, selector: "[translate],[ngx-translate]", inputs: ["translate", "translateParams"] }], pipes: { "translate": i1.TranslatePipe } });
|
|
1698
2017
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: MessageActionsBoxComponent, decorators: [{
|
|
1699
2018
|
type: Component,
|
|
1700
2019
|
args: [{
|
|
@@ -1727,10 +2046,11 @@ class ChannelComponent {
|
|
|
1727
2046
|
this.subscriptions = [];
|
|
1728
2047
|
this.isError$ = this.channelService.channels$.pipe(map(() => false), catchError(() => of(true)), startWith(false));
|
|
1729
2048
|
this.isInitializing$ = this.channelService.channels$.pipe(map((channels) => !channels), catchError(() => of(false)));
|
|
2049
|
+
this.isActiveThread$ = this.channelService.activeParentMessageId$.pipe(map((id) => !!id));
|
|
1730
2050
|
}
|
|
1731
2051
|
}
|
|
1732
2052
|
ChannelComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: ChannelComponent, deps: [{ token: ChannelService }], target: i0.ɵɵFactoryTarget.Component });
|
|
1733
|
-
ChannelComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.5", type: ChannelComponent, selector: "stream-channel", ngImport: i0, template: "<div\n *ngIf=\"(isError$ | async) === false && (isInitializing$ | async) === false\"\n class=\"str-chat str-chat-channel messaging\"\n>\n <div class=\"str-chat__container\">\n <div class=\"str-chat__main-panel\">\n <ng-content></ng-content>\n </div>\n </div>\n</div>\n", directives: [{ type:
|
|
2053
|
+
ChannelComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.5", type: ChannelComponent, selector: "stream-channel", ngImport: i0, template: "<div\n *ngIf=\"(isError$ | async) === false && (isInitializing$ | async) === false\"\n class=\"str-chat str-chat-channel messaging\"\n>\n <div class=\"str-chat__container\">\n <div class=\"str-chat__main-panel\">\n <ng-content></ng-content>\n </div>\n <ng-content\n *ngIf=\"isActiveThread$ | async\"\n select='[name=\"thread\"]'\n ></ng-content>\n </div>\n</div>\n", directives: [{ type: i6.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }], pipes: { "async": i6.AsyncPipe } });
|
|
1734
2054
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: ChannelComponent, decorators: [{
|
|
1735
2055
|
type: Component,
|
|
1736
2056
|
args: [{
|
|
@@ -1830,7 +2150,7 @@ class ChannelHeaderComponent {
|
|
|
1830
2150
|
}
|
|
1831
2151
|
}
|
|
1832
2152
|
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 });
|
|
1833
|
-
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":
|
|
2153
|
+
ChannelHeaderComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.5", type: ChannelHeaderComponent, selector: "stream-channel-header", ngImport: i0, template: "<div class=\"str-chat__header-livestream\">\n <div\n class=\"str-chat__header-hamburger\"\n (click)=\"toggleMenu($event)\"\n (keyup.enter)=\"toggleMenu($event)\"\n >\n <span class=\"str-chat__header-hamburger--line\"></span>\n <span class=\"str-chat__header-hamburger--line\"></span>\n <span class=\"str-chat__header-hamburger--line\"></span>\n </div>\n <stream-avatar\n imageUrl=\"{{ activeChannel?.data?.image }}\"\n name=\"{{ activeChannel?.data?.name }}\"\n ></stream-avatar>\n <div class=\"str-chat__header-livestream-left\">\n <p data-testid=\"name\" class=\"str-chat__header-livestream-left--title\">\n {{ activeChannel?.data?.name }}\n </p>\n <p data-testid=\"info\" class=\"str-chat__header-livestream-left--members\">\n {{'streamChat.{{ memberCount }} members' | translate:memberCountParam}}\n {{canReceiveConnectEvents ? ('streamChat.{{ watcherCount }} online' |\n translate:watcherCountParam) : ''}}\n </p>\n </div>\n</div>\n", components: [{ type: AvatarComponent, selector: "stream-avatar", inputs: ["name", "imageUrl", "size"] }], pipes: { "translate": i1.TranslatePipe } });
|
|
1834
2154
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: ChannelHeaderComponent, decorators: [{
|
|
1835
2155
|
type: Component,
|
|
1836
2156
|
args: [{
|
|
@@ -1915,7 +2235,7 @@ class ChannelPreviewComponent {
|
|
|
1915
2235
|
}
|
|
1916
2236
|
}
|
|
1917
2237
|
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 });
|
|
1918
|
-
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":
|
|
2238
|
+
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": i1.TranslatePipe } });
|
|
1919
2239
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: ChannelPreviewComponent, decorators: [{
|
|
1920
2240
|
type: Component,
|
|
1921
2241
|
args: [{
|
|
@@ -1956,7 +2276,7 @@ class ChannelListComponent {
|
|
|
1956
2276
|
}
|
|
1957
2277
|
}
|
|
1958
2278
|
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 });
|
|
1959
|
-
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:
|
|
2279
|
+
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": i1.TranslatePipe } });
|
|
1960
2280
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: ChannelListComponent, decorators: [{
|
|
1961
2281
|
type: Component,
|
|
1962
2282
|
args: [{
|
|
@@ -2107,7 +2427,7 @@ class MessageReactionsComponent {
|
|
|
2107
2427
|
}
|
|
2108
2428
|
}
|
|
2109
2429
|
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 });
|
|
2110
|
-
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\"\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:
|
|
2430
|
+
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\"\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"] }] });
|
|
2111
2431
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: MessageReactionsComponent, decorators: [{
|
|
2112
2432
|
type: Component,
|
|
2113
2433
|
args: [{
|
|
@@ -2135,83 +2455,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImpor
|
|
|
2135
2455
|
args: ['selectorTooltip']
|
|
2136
2456
|
}] } });
|
|
2137
2457
|
|
|
2138
|
-
class ImageLoadService {
|
|
2139
|
-
constructor() {
|
|
2140
|
-
this.imageLoad$ = new Subject();
|
|
2141
|
-
}
|
|
2142
|
-
}
|
|
2143
|
-
ImageLoadService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: ImageLoadService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
2144
|
-
ImageLoadService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: ImageLoadService, providedIn: 'root' });
|
|
2145
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: ImageLoadService, decorators: [{
|
|
2146
|
-
type: Injectable,
|
|
2147
|
-
args: [{
|
|
2148
|
-
providedIn: 'root',
|
|
2149
|
-
}]
|
|
2150
|
-
}], ctorParameters: function () { return []; } });
|
|
2151
|
-
|
|
2152
|
-
class AttachmentListComponent {
|
|
2153
|
-
constructor(imageLoadService) {
|
|
2154
|
-
this.imageLoadService = imageLoadService;
|
|
2155
|
-
this.attachments = [];
|
|
2156
|
-
this.orderedAttachments = [];
|
|
2157
|
-
}
|
|
2158
|
-
ngOnChanges() {
|
|
2159
|
-
this.orderedAttachments = [
|
|
2160
|
-
...this.attachments.filter((a) => this.isImage(a)),
|
|
2161
|
-
...this.attachments.filter((a) => this.isFile(a)),
|
|
2162
|
-
...this.attachments.filter((a) => this.isCard(a)),
|
|
2163
|
-
];
|
|
2164
|
-
}
|
|
2165
|
-
trackById(index) {
|
|
2166
|
-
return index;
|
|
2167
|
-
}
|
|
2168
|
-
isImage(attachment) {
|
|
2169
|
-
return isImageAttachment(attachment);
|
|
2170
|
-
}
|
|
2171
|
-
isFile(attachment) {
|
|
2172
|
-
return attachment.type === 'file';
|
|
2173
|
-
}
|
|
2174
|
-
isCard(attachment) {
|
|
2175
|
-
return (!attachment.type ||
|
|
2176
|
-
(attachment.type === 'image' && !this.isImage(attachment)));
|
|
2177
|
-
}
|
|
2178
|
-
imageLoaded() {
|
|
2179
|
-
this.imageLoadService.imageLoad$.next();
|
|
2180
|
-
}
|
|
2181
|
-
hasFileSize(attachment) {
|
|
2182
|
-
return (attachment.file_size && Number.isFinite(Number(attachment.file_size)));
|
|
2183
|
-
}
|
|
2184
|
-
getFileSize(attachment) {
|
|
2185
|
-
return prettybytes(attachment.file_size);
|
|
2186
|
-
}
|
|
2187
|
-
trimUrl(url) {
|
|
2188
|
-
if (url !== undefined && url !== null) {
|
|
2189
|
-
const [trimmedUrl] = url
|
|
2190
|
-
.replace(/^(?:https?:\/\/)?(?:www\.)?/i, '')
|
|
2191
|
-
.split('/');
|
|
2192
|
-
return trimmedUrl;
|
|
2193
|
-
}
|
|
2194
|
-
return null;
|
|
2195
|
-
}
|
|
2196
|
-
}
|
|
2197
|
-
AttachmentListComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: AttachmentListComponent, deps: [{ token: ImageLoadService }], target: i0.ɵɵFactoryTarget.Component });
|
|
2198
|
-
AttachmentListComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.5", type: AttachmentListComponent, selector: "stream-attachment-list", inputs: { attachments: "attachments" }, usesOnChanges: true, ngImport: i0, template: "<ng-container *ngFor=\"let attachment of orderedAttachments; trackBy: trackById\">\n <div\n data-testclass=\"attachment-container\"\n class=\"str-chat__message-attachment str-chat__message-attachment--{{\n attachment.type\n }}\"\n [class.str-chat__message-attachment--card]=\"isCard(attachment)\"\n [class.str-chat-angular__message-attachment-file-single]=\"\n isFile(attachment)\n \"\n >\n <img\n *ngIf=\"isImage(attachment)\"\n class=\"str-chat__message-attachment--img\"\n data-testclass=\"image\"\n [src]=\"attachment.img_url || attachment.thumb_url || attachment.image_url\"\n [alt]=\"attachment?.fallback\"\n (load)=\"imageLoaded()\"\n />\n <div\n *ngIf=\"isFile(attachment)\"\n class=\"\n str-chat__message-attachment-file--item\n str-chat-angular__message-attachment-file-single\n \"\n >\n <stream-icon icon=\"file\" [size]=\"30\"></stream-icon>\n <div class=\"str-chat__message-attachment-file--item-text\">\n <a\n data-testclass=\"file-link\"\n download\n href=\"{{ attachment.asset_url }}\"\n target=\"_blank\"\n >\n {{ attachment.title }}\n </a>\n <span data-testclass=\"size\" *ngIf=\"hasFileSize(attachment)\">{{\n getFileSize(attachment)\n }}</span>\n </div>\n </div>\n <div\n *ngIf=\"isCard(attachment)\"\n class=\"str-chat__message-attachment-card str-chat__message-attachment-card--{{\n attachment.type\n }}\"\n >\n <div\n *ngIf=\"attachment.image_url || attachment.thumb_url\"\n class=\"str-chat__message-attachment-card--header\"\n >\n <img\n data-testclass=\"card-img\"\n alt=\"{{ attachment.image_url || attachment.thumb_url }}\"\n src=\"{{ attachment.image_url || attachment.thumb_url }}\"\n />\n </div>\n <div class=\"str-chat__message-attachment-card--content\">\n <div class=\"str-chat__message-attachment-card--flex\">\n <div\n *ngIf=\"attachment.title\"\n data-testclass=\"card-title\"\n class=\"str-chat__message-attachment-card--title\"\n >\n {{ attachment.title }}\n </div>\n <div\n *ngIf=\"attachment.text\"\n class=\"str-chat__message-attachment-card--text\"\n data-testclass=\"card-text\"\n >\n {{ attachment.text }}\n </div>\n <a\n class=\"str-chat__message-attachment-card--url\"\n *ngIf=\"attachment.title_link || attachment.og_scrape_url\"\n data-testclass=\"url-link\"\n noopener\n noreferrer\n href=\"{{ attachment.title_link || attachment.og_scrape_url }}\"\n target=\"_blank\"\n >\n {{ trimUrl(attachment.title_link || attachment.og_scrape_url) }}\n </a>\n </div>\n </div>\n </div>\n </div>\n</ng-container>\n", components: [{ type: IconComponent, selector: "stream-icon", inputs: ["icon", "size"] }], directives: [{ type: i3.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }] });
|
|
2199
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: AttachmentListComponent, decorators: [{
|
|
2200
|
-
type: Component,
|
|
2201
|
-
args: [{
|
|
2202
|
-
selector: 'stream-attachment-list',
|
|
2203
|
-
templateUrl: './attachment-list.component.html',
|
|
2204
|
-
styles: [],
|
|
2205
|
-
}]
|
|
2206
|
-
}], ctorParameters: function () { return [{ type: ImageLoadService }]; }, propDecorators: { attachments: [{
|
|
2207
|
-
type: Input
|
|
2208
|
-
}] } });
|
|
2209
|
-
|
|
2210
2458
|
class MessageComponent {
|
|
2211
2459
|
constructor(chatClientService, channelService) {
|
|
2212
2460
|
this.chatClientService = chatClientService;
|
|
2213
2461
|
this.channelService = channelService;
|
|
2214
2462
|
this.enabledMessageActions = [];
|
|
2463
|
+
this.mode = 'main';
|
|
2215
2464
|
this.isActionBoxOpen = false;
|
|
2216
2465
|
this.isReactionSelectorOpen = false;
|
|
2217
2466
|
this.isPressedOnMobile = false;
|
|
@@ -2220,46 +2469,8 @@ class MessageComponent {
|
|
|
2220
2469
|
this.user = this.chatClientService.chatClient.user;
|
|
2221
2470
|
}
|
|
2222
2471
|
ngOnChanges(changes) {
|
|
2223
|
-
var _a, _b;
|
|
2224
2472
|
if (changes.message) {
|
|
2225
|
-
|
|
2226
|
-
if (!content) {
|
|
2227
|
-
this.messageTextParts = [];
|
|
2228
|
-
}
|
|
2229
|
-
else {
|
|
2230
|
-
// Backend will wrap HTML content with <p></p>\n
|
|
2231
|
-
if (content.startsWith('<p>')) {
|
|
2232
|
-
content = content.replace('<p>', '');
|
|
2233
|
-
}
|
|
2234
|
-
if (content.endsWith('</p>\n')) {
|
|
2235
|
-
content = content.replace('</p>\n', '');
|
|
2236
|
-
}
|
|
2237
|
-
if (!this.message.mentioned_users ||
|
|
2238
|
-
this.message.mentioned_users.length === 0) {
|
|
2239
|
-
this.messageTextParts = [{ content, type: 'text' }];
|
|
2240
|
-
}
|
|
2241
|
-
else {
|
|
2242
|
-
this.messageTextParts = [];
|
|
2243
|
-
let text = content;
|
|
2244
|
-
this.message.mentioned_users.forEach((user) => {
|
|
2245
|
-
const mention = `@${user.name || user.id}`;
|
|
2246
|
-
const precedingText = text.substring(0, text.indexOf(mention));
|
|
2247
|
-
this.messageTextParts.push({
|
|
2248
|
-
content: precedingText,
|
|
2249
|
-
type: 'text',
|
|
2250
|
-
});
|
|
2251
|
-
this.messageTextParts.push({
|
|
2252
|
-
content: mention,
|
|
2253
|
-
type: 'mention',
|
|
2254
|
-
user,
|
|
2255
|
-
});
|
|
2256
|
-
text = text.replace(precedingText + mention, '');
|
|
2257
|
-
});
|
|
2258
|
-
if (text) {
|
|
2259
|
-
this.messageTextParts.push({ content: text, type: 'text' });
|
|
2260
|
-
}
|
|
2261
|
-
}
|
|
2262
|
-
}
|
|
2473
|
+
this.createMessageParts();
|
|
2263
2474
|
}
|
|
2264
2475
|
}
|
|
2265
2476
|
get isSentByCurrentUser() {
|
|
@@ -2301,7 +2512,8 @@ class MessageComponent {
|
|
|
2301
2512
|
this.message.type === 'system' ||
|
|
2302
2513
|
this.message.type === 'ephemeral' ||
|
|
2303
2514
|
this.message.status === 'failed' ||
|
|
2304
|
-
this.message.status === 'sending'
|
|
2515
|
+
this.message.status === 'sending' ||
|
|
2516
|
+
(this.mode === 'thread' && !this.message.parent_id));
|
|
2305
2517
|
}
|
|
2306
2518
|
get hasAttachment() {
|
|
2307
2519
|
var _a;
|
|
@@ -2312,6 +2524,21 @@ class MessageComponent {
|
|
|
2312
2524
|
return (!!((_a = this.message) === null || _a === void 0 ? void 0 : _a.reaction_counts) &&
|
|
2313
2525
|
Object.keys(this.message.reaction_counts).length > 0);
|
|
2314
2526
|
}
|
|
2527
|
+
get replyCountParam() {
|
|
2528
|
+
var _a;
|
|
2529
|
+
return { replyCount: (_a = this.message) === null || _a === void 0 ? void 0 : _a.reply_count };
|
|
2530
|
+
}
|
|
2531
|
+
get canDisplayReadStatus() {
|
|
2532
|
+
return (this.canReceiveReadEvents !== false &&
|
|
2533
|
+
this.enabledMessageActions.indexOf('read-events') !== -1);
|
|
2534
|
+
}
|
|
2535
|
+
get quotedMessageAttachments() {
|
|
2536
|
+
var _a, _b;
|
|
2537
|
+
const originalAttachments = (_b = (_a = this.message) === null || _a === void 0 ? void 0 : _a.quoted_message) === null || _b === void 0 ? void 0 : _b.attachments;
|
|
2538
|
+
return originalAttachments && originalAttachments.length
|
|
2539
|
+
? [originalAttachments[0]]
|
|
2540
|
+
: [];
|
|
2541
|
+
}
|
|
2315
2542
|
resendMessage() {
|
|
2316
2543
|
void this.channelService.resendMessage(this.message);
|
|
2317
2544
|
}
|
|
@@ -2333,9 +2560,53 @@ class MessageComponent {
|
|
|
2333
2560
|
};
|
|
2334
2561
|
window.addEventListener('click', eventHandler);
|
|
2335
2562
|
}
|
|
2563
|
+
setAsActiveParentMessage() {
|
|
2564
|
+
void this.channelService.setAsActiveParentMessage(this.message);
|
|
2565
|
+
}
|
|
2566
|
+
createMessageParts() {
|
|
2567
|
+
var _a, _b;
|
|
2568
|
+
let content = ((_a = this.message) === null || _a === void 0 ? void 0 : _a.html) || ((_b = this.message) === null || _b === void 0 ? void 0 : _b.text);
|
|
2569
|
+
if (!content) {
|
|
2570
|
+
this.messageTextParts = [];
|
|
2571
|
+
}
|
|
2572
|
+
else {
|
|
2573
|
+
// Backend will wrap HTML content with <p></p>\n
|
|
2574
|
+
if (content.startsWith('<p>')) {
|
|
2575
|
+
content = content.replace('<p>', '');
|
|
2576
|
+
}
|
|
2577
|
+
if (content.endsWith('</p>\n')) {
|
|
2578
|
+
content = content.replace('</p>\n', '');
|
|
2579
|
+
}
|
|
2580
|
+
if (!this.message.mentioned_users ||
|
|
2581
|
+
this.message.mentioned_users.length === 0) {
|
|
2582
|
+
this.messageTextParts = [{ content, type: 'text' }];
|
|
2583
|
+
}
|
|
2584
|
+
else {
|
|
2585
|
+
this.messageTextParts = [];
|
|
2586
|
+
let text = content;
|
|
2587
|
+
this.message.mentioned_users.forEach((user) => {
|
|
2588
|
+
const mention = `@${user.name || user.id}`;
|
|
2589
|
+
const precedingText = text.substring(0, text.indexOf(mention));
|
|
2590
|
+
this.messageTextParts.push({
|
|
2591
|
+
content: precedingText,
|
|
2592
|
+
type: 'text',
|
|
2593
|
+
});
|
|
2594
|
+
this.messageTextParts.push({
|
|
2595
|
+
content: mention,
|
|
2596
|
+
type: 'mention',
|
|
2597
|
+
user,
|
|
2598
|
+
});
|
|
2599
|
+
text = text.replace(precedingText + mention, '');
|
|
2600
|
+
});
|
|
2601
|
+
if (text) {
|
|
2602
|
+
this.messageTextParts.push({ content: text, type: 'text' });
|
|
2603
|
+
}
|
|
2604
|
+
}
|
|
2605
|
+
}
|
|
2606
|
+
}
|
|
2336
2607
|
}
|
|
2337
2608
|
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 });
|
|
2338
|
-
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" }, 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 && hasReactions\n \"\n data-testid=\"message-container\"\n>\n <ng-container *ngIf=\"!message?.deleted_at; else deletedMessage\">\n <ng-container *ngIf=\"message?.type !== 'system'; else systemMessage\">\n <ng-container\n *ngIf=\"\n isSentByCurrentUser &&\n ((isLastSentMessage && message?.status === 'received') ||\n message?.status === 'sending')\n \"\n >\n <ng-container *ngIf=\"message?.status === 'sending'; else sentStatus\">\n <ng-container *ngTemplateOutlet=\"sendingStatus\"></ng-container>\n </ng-container>\n <ng-template #sentStatus>\n <ng-container\n *ngIf=\"\n isMessageDeliveredAndRead && canReceiveReadEvents;\n else deliveredStatus\n \"\n >\n <ng-container *ngTemplateOutlet=\"readStatus\"></ng-container>\n </ng-container>\n </ng-template>\n </ng-container>\n <stream-avatar\n data-testid=\"avatar\"\n class=\"str-chat-angular__avatar-host\"\n [imageUrl]=\"message?.user?.image\"\n [name]=\"message?.user?.name || message?.user?.id\"\n ></stream-avatar>\n <div class=\"str-chat__message-inner\">\n <div\n class=\"str-chat__message-simple__actions\"\n data-testid=\"message-options\"\n *ngIf=\"areOptionsVisible\"\n >\n <div\n data-testid=\"message-actions-container\"\n class=\"\n str-chat__message-simple__actions__action\n str-chat__message-simple__actions__action--options\n \"\n [class.str-chat-angular__message-simple__actions__action--options--editing]=\"\n isEditing\n \"\n >\n <stream-message-actions-box\n [isOpen]=\"isActionBoxOpen\"\n [isMine]=\"isSentByCurrentUser\"\n [enabledActions]=\"enabledMessageActions\"\n [message]=\"message\"\n (displayedActionsCount)=\"visibleMessageActionsCount = $event\"\n (isEditing)=\"isEditing = $event; isActionBoxOpen = !isEditing\"\n [messageInputTemplate]=\"messageInputTemplate\"\n ></stream-message-actions-box>\n <stream-icon\n *ngIf=\"visibleMessageActionsCount > 0\"\n data-testid=\"action-icon\"\n icon=\"action-icon\"\n (keyup.enter)=\"isActionBoxOpen = !isActionBoxOpen\"\n (click)=\"isActionBoxOpen = !isActionBoxOpen\"\n ></stream-icon>\n </div>\n <div\n *ngIf=\"areReactionsEnabled && canReactToMessage\"\n class=\"\n str-chat__message-simple__actions__action\n str-chat__message-simple__actions__action--reactions\n \"\n data-testid=\"reaction-icon\"\n (click)=\"isReactionSelectorOpen = !isReactionSelectorOpen\"\n (keyup.enter)=\"isReactionSelectorOpen = !isReactionSelectorOpen\"\n >\n <stream-icon icon=\"reaction-icon\"></stream-icon>\n </div>\n </div>\n <stream-message-reactions\n *ngIf=\"areReactionsEnabled\"\n [messageReactionCounts]=\"message?.reaction_counts || {}\"\n [latestReactions]=\"message?.latest_reactions || []\"\n [(isSelectorOpen)]=\"isReactionSelectorOpen\"\n [messageId]=\"message?.id\"\n [ownReactions]=\"message?.own_reactions || []\"\n ></stream-message-reactions>\n <stream-attachment-list\n *ngIf=\"hasAttachment\"\n [attachments]=\"message!.attachments!\"\n ></stream-attachment-list>\n <div class=\"str-chat__message-text\" *ngIf=\"message?.text\">\n <div\n data-testid=\"inner-message\"\n class=\"\n str-chat__message-text-inner str-chat__message-simple-text-inner\n \"\n [class.str-chat__message-light-text-inner--has-attachment]=\"\n hasAttachment\n \"\n (click)=\"\n message?.status === 'failed' && message?.errorStatusCode !== 403\n ? resendMessage()\n : undefined\n \"\n (keyup.enter)=\"\n message?.status === 'failed' && message?.errorStatusCode !== 403\n ? resendMessage()\n : undefined\n \"\n >\n <div\n data-testid=\"client-error-message\"\n *ngIf=\"message?.type === 'error'\"\n class=\"str-chat__simple-message--error-message\"\n >\n {{ \"streamChat.Error \u00B7 Unsent\" | translate }}\n </div>\n <div\n data-testid=\"error-message\"\n *ngIf=\"message?.status === 'failed'\"\n class=\"str-chat__simple-message--error-message\"\n >\n {{\n (message?.errorStatusCode === 403\n ? \"streamChat.Message Failed \u00B7 Unauthorized\"\n : \"streamChat.Message Failed \u00B7 Click to try again\"\n ) | translate\n }}\n </div>\n <div\n (click)=\"textClicked()\"\n (keyup.enter)=\"textClicked()\"\n data-testid=\"text\"\n >\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-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 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", components: [{ type: AvatarComponent, selector: "stream-avatar", inputs: ["name", "imageUrl", "size"] }, { type: MessageActionsBoxComponent, selector: "stream-message-actions-box", inputs: ["messageInputTemplate", "isOpen", "isMine", "message", "enabledActions"], outputs: ["displayedActionsCount", "isEditing"] }, { type: IconComponent, selector: "stream-icon", inputs: ["icon", "size"] }, { type: MessageReactionsComponent, selector: "stream-message-reactions", inputs: ["messageId", "messageReactionCounts", "isSelectorOpen", "latestReactions", "ownReactions"], outputs: ["isSelectorOpenChange"] }, { type: AttachmentListComponent, selector: "stream-attachment-list", inputs: ["attachments"] }, { type: LoadingIndicatorComponent, selector: "stream-loading-indicator", inputs: ["size", "color"] }], directives: [{ type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i3.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet"] }, { type: i3.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i10.TranslateDirective, selector: "[translate],[ngx-translate]", inputs: ["translate", "translateParams"] }], pipes: { "translate": i10.TranslatePipe } });
|
|
2609
|
+
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>\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 } });
|
|
2339
2610
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: MessageComponent, decorators: [{
|
|
2340
2611
|
type: Component,
|
|
2341
2612
|
args: [{
|
|
@@ -2359,6 +2630,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImpor
|
|
|
2359
2630
|
type: Input
|
|
2360
2631
|
}], canReceiveReadEvents: [{
|
|
2361
2632
|
type: Input
|
|
2633
|
+
}], mode: [{
|
|
2634
|
+
type: Input
|
|
2362
2635
|
}], container: [{
|
|
2363
2636
|
type: ViewChild,
|
|
2364
2637
|
args: ['container']
|
|
@@ -2382,7 +2655,7 @@ class TextareaComponent {
|
|
|
2382
2655
|
}
|
|
2383
2656
|
}
|
|
2384
2657
|
TextareaComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: TextareaComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2385
|
-
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":
|
|
2658
|
+
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": i1.TranslatePipe } });
|
|
2386
2659
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: TextareaComponent, decorators: [{
|
|
2387
2660
|
type: Component,
|
|
2388
2661
|
args: [{
|
|
@@ -2428,8 +2701,9 @@ class AutocompleteTextareaComponent {
|
|
|
2428
2701
|
this.valueChange = new EventEmitter();
|
|
2429
2702
|
this.send = new EventEmitter();
|
|
2430
2703
|
this.userMentions = new EventEmitter();
|
|
2431
|
-
this.
|
|
2704
|
+
this.autocompleteKey = 'autocompleteLabel';
|
|
2432
2705
|
this.mentionTriggerChar = '@';
|
|
2706
|
+
this.commandTriggerChar = '/';
|
|
2433
2707
|
this.autocompleteConfig = {
|
|
2434
2708
|
mentions: [],
|
|
2435
2709
|
};
|
|
@@ -2438,7 +2712,15 @@ class AutocompleteTextareaComponent {
|
|
|
2438
2712
|
this.userMentionConfig = {
|
|
2439
2713
|
triggerChar: this.mentionTriggerChar,
|
|
2440
2714
|
dropUp: true,
|
|
2441
|
-
labelKey: this.
|
|
2715
|
+
labelKey: this.autocompleteKey,
|
|
2716
|
+
returnTrigger: true,
|
|
2717
|
+
mentionFilter: (searchString, items) => this.filter(searchString, items),
|
|
2718
|
+
mentionSelect: (item, triggerChar) => this.itemSelectedFromAutocompleteList(item, triggerChar),
|
|
2719
|
+
};
|
|
2720
|
+
this.slashCommandConfig = {
|
|
2721
|
+
triggerChar: this.commandTriggerChar,
|
|
2722
|
+
dropUp: true,
|
|
2723
|
+
labelKey: 'name',
|
|
2442
2724
|
returnTrigger: true,
|
|
2443
2725
|
mentionFilter: (searchString, items) => this.filter(searchString, items),
|
|
2444
2726
|
mentionSelect: (item, triggerChar) => this.itemSelectedFromAutocompleteList(item, triggerChar),
|
|
@@ -2451,20 +2733,30 @@ class AutocompleteTextareaComponent {
|
|
|
2451
2733
|
void this.updateMentionOptions(searchTerm);
|
|
2452
2734
|
}
|
|
2453
2735
|
});
|
|
2454
|
-
this.subscriptions.push(this.channelService.activeChannel$.subscribe(() => {
|
|
2736
|
+
this.subscriptions.push(this.channelService.activeChannel$.subscribe((channel) => {
|
|
2737
|
+
var _a;
|
|
2738
|
+
const commands = ((_a = channel === null || channel === void 0 ? void 0 : channel.getConfig()) === null || _a === void 0 ? void 0 : _a.commands) || [];
|
|
2739
|
+
this.slashCommandConfig.items = commands.map((c) => (Object.assign(Object.assign({}, c), { [this.autocompleteKey]: c.name, type: 'command' })));
|
|
2455
2740
|
this.mentionedUsers = [];
|
|
2456
2741
|
this.userMentions.next([...this.mentionedUsers]);
|
|
2457
2742
|
void this.updateMentionOptions(this.searchTerm$.getValue());
|
|
2458
2743
|
}));
|
|
2744
|
+
this.autocompleteConfig.mentions = [
|
|
2745
|
+
this.userMentionConfig,
|
|
2746
|
+
this.slashCommandConfig,
|
|
2747
|
+
];
|
|
2459
2748
|
}
|
|
2460
2749
|
ngOnChanges(changes) {
|
|
2461
2750
|
if (changes.areMentionsEnabled) {
|
|
2462
2751
|
if (this.areMentionsEnabled) {
|
|
2463
|
-
this.autocompleteConfig.mentions = [
|
|
2752
|
+
this.autocompleteConfig.mentions = [
|
|
2753
|
+
this.userMentionConfig,
|
|
2754
|
+
this.slashCommandConfig,
|
|
2755
|
+
];
|
|
2464
2756
|
this.autocompleteConfig = Object.assign({}, this.autocompleteConfig);
|
|
2465
2757
|
}
|
|
2466
2758
|
else {
|
|
2467
|
-
this.autocompleteConfig.mentions = [];
|
|
2759
|
+
this.autocompleteConfig.mentions = [this.slashCommandConfig];
|
|
2468
2760
|
this.autocompleteConfig = Object.assign({}, this.autocompleteConfig);
|
|
2469
2761
|
}
|
|
2470
2762
|
}
|
|
@@ -2480,7 +2772,9 @@ class AutocompleteTextareaComponent {
|
|
|
2480
2772
|
this.mentionedUsers.push((item.user ? item.user : item));
|
|
2481
2773
|
this.userMentions.next([...this.mentionedUsers]);
|
|
2482
2774
|
}
|
|
2483
|
-
return triggerChar +
|
|
2775
|
+
return (triggerChar +
|
|
2776
|
+
item.autocompleteLabel +
|
|
2777
|
+
(triggerChar === this.commandTriggerChar ? ' ' : ''));
|
|
2484
2778
|
}
|
|
2485
2779
|
autcompleteSearchTermChanged(searchTerm) {
|
|
2486
2780
|
if (searchTerm === this.mentionTriggerChar) {
|
|
@@ -2524,7 +2818,10 @@ class AutocompleteTextareaComponent {
|
|
|
2524
2818
|
return Object.assign(Object.assign({}, i), { autocompleteLabel: user.name || user.id, type: 'mention' });
|
|
2525
2819
|
}));
|
|
2526
2820
|
this.userMentionConfig.items = items;
|
|
2527
|
-
this.autocompleteConfig.mentions = [
|
|
2821
|
+
this.autocompleteConfig.mentions = [
|
|
2822
|
+
this.userMentionConfig,
|
|
2823
|
+
this.slashCommandConfig,
|
|
2824
|
+
];
|
|
2528
2825
|
this.autocompleteConfig = Object.assign({}, this.autocompleteConfig);
|
|
2529
2826
|
});
|
|
2530
2827
|
}
|
|
@@ -2543,7 +2840,7 @@ class AutocompleteTextareaComponent {
|
|
|
2543
2840
|
}
|
|
2544
2841
|
}
|
|
2545
2842
|
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 });
|
|
2546
|
-
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", 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>\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: i5.MentionDirective, selector: "[mention], [mentionConfig]", inputs: ["mentionConfig", "mention", "mentionListTemplate"], outputs: ["searchTerm", "itemSelected", "opened", "closed"] }, { type:
|
|
2843
|
+
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: i5.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": i1.TranslatePipe } });
|
|
2547
2844
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: AutocompleteTextareaComponent, decorators: [{
|
|
2548
2845
|
type: Component,
|
|
2549
2846
|
args: [{
|
|
@@ -2559,6 +2856,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImpor
|
|
|
2559
2856
|
type: Input
|
|
2560
2857
|
}], mentionAutocompleteItemTemplate: [{
|
|
2561
2858
|
type: Input
|
|
2859
|
+
}], commandAutocompleteItemTemplate: [{
|
|
2860
|
+
type: Input
|
|
2562
2861
|
}], mentionScope: [{
|
|
2563
2862
|
type: Input
|
|
2564
2863
|
}], valueChange: [{
|
|
@@ -2617,30 +2916,37 @@ class MessageListComponent {
|
|
|
2617
2916
|
this.channelService = channelService;
|
|
2618
2917
|
this.chatClientService = chatClientService;
|
|
2619
2918
|
this.imageLoadService = imageLoadService;
|
|
2620
|
-
|
|
2919
|
+
/**
|
|
2920
|
+
* @deprecated https://getstream.io/chat/docs/sdk/angular/components/message_list/#caution-arereactionsenabled-deprecated
|
|
2921
|
+
*/
|
|
2922
|
+
this.areReactionsEnabled = undefined;
|
|
2923
|
+
/**
|
|
2924
|
+
* @deprecated https://getstream.io/chat/docs/sdk/angular/components/message_list/#caution-enabledmessageactions-deprecated
|
|
2925
|
+
*/
|
|
2621
2926
|
/* eslint-disable-next-line @angular-eslint/no-input-rename */
|
|
2622
|
-
this.enabledMessageActionsInput =
|
|
2927
|
+
this.enabledMessageActionsInput = undefined;
|
|
2928
|
+
this.mode = 'main';
|
|
2623
2929
|
this.enabledMessageActions = [];
|
|
2624
2930
|
this.class = 'str-chat-angular__main-panel-inner str-chat-angular__message-list-host';
|
|
2625
2931
|
this.unreadMessageCount = 0;
|
|
2626
2932
|
this.groupStyles = [];
|
|
2627
2933
|
this.authorizedMessageActions = ['flag'];
|
|
2628
2934
|
this.isUserScrolledUpThreshold = 300;
|
|
2629
|
-
this.
|
|
2935
|
+
this.subscriptions = [];
|
|
2936
|
+
this.subscriptions.push(this.channelService.activeChannel$.subscribe((channel) => {
|
|
2630
2937
|
var _a;
|
|
2631
|
-
this.
|
|
2632
|
-
this.hasNewMessages = true;
|
|
2633
|
-
this.isUserScrolledUp = false;
|
|
2634
|
-
this.containerHeight = undefined;
|
|
2635
|
-
this.olderMassagesLoaded = false;
|
|
2636
|
-
this.oldestMessageDate = undefined;
|
|
2637
|
-
this.unreadMessageCount = 0;
|
|
2638
|
-
this.isNewMessageSentByUser = undefined;
|
|
2938
|
+
this.resetScrollState();
|
|
2639
2939
|
const capabilites = (_a = channel === null || channel === void 0 ? void 0 : channel.data) === null || _a === void 0 ? void 0 : _a.own_capabilities;
|
|
2640
2940
|
if (capabilites) {
|
|
2641
2941
|
this.canReactToMessage = capabilites.indexOf('send-reaction') !== -1;
|
|
2642
2942
|
this.canReceiveReadEvents = capabilites.indexOf('read-events') !== -1;
|
|
2643
2943
|
this.authorizedMessageActions = [];
|
|
2944
|
+
if (this.canReactToMessage) {
|
|
2945
|
+
this.authorizedMessageActions.push('send-reaction');
|
|
2946
|
+
}
|
|
2947
|
+
if (this.canReceiveReadEvents) {
|
|
2948
|
+
this.authorizedMessageActions.push('read-events');
|
|
2949
|
+
}
|
|
2644
2950
|
if (capabilites.indexOf('flag-message') !== -1) {
|
|
2645
2951
|
this.authorizedMessageActions.push('flag');
|
|
2646
2952
|
}
|
|
@@ -2658,47 +2964,16 @@ class MessageListComponent {
|
|
|
2658
2964
|
this.authorizedMessageActions.push('delete');
|
|
2659
2965
|
this.authorizedMessageActions.push('delete-any');
|
|
2660
2966
|
}
|
|
2661
|
-
|
|
2662
|
-
|
|
2663
|
-
});
|
|
2664
|
-
this.messages$ = this.channelService.activeChannelMessages$.pipe(tap((messages) => {
|
|
2665
|
-
var _a, _b, _c, _d, _e;
|
|
2666
|
-
if (messages.length === 0) {
|
|
2667
|
-
return;
|
|
2668
|
-
}
|
|
2669
|
-
const currentLatestMessageDate = messages[messages.length - 1].created_at;
|
|
2670
|
-
if (!this.latestMessageDate ||
|
|
2671
|
-
((_a = this.latestMessageDate) === null || _a === void 0 ? void 0 : _a.getTime()) < currentLatestMessageDate.getTime()) {
|
|
2672
|
-
this.latestMessageDate = currentLatestMessageDate;
|
|
2673
|
-
this.hasNewMessages = true;
|
|
2674
|
-
this.isNewMessageSentByUser =
|
|
2675
|
-
((_b = messages[messages.length - 1].user) === null || _b === void 0 ? void 0 : _b.id) ===
|
|
2676
|
-
((_d = (_c = this.chatClientService.chatClient) === null || _c === void 0 ? void 0 : _c.user) === null || _d === void 0 ? void 0 : _d.id);
|
|
2677
|
-
if (this.isUserScrolledUp) {
|
|
2678
|
-
this.unreadMessageCount++;
|
|
2967
|
+
if (capabilites.indexOf('send-reply') !== -1) {
|
|
2968
|
+
this.authorizedMessageActions.push('send-reply');
|
|
2679
2969
|
}
|
|
2970
|
+
if (capabilites.indexOf('quote-message') !== -1) {
|
|
2971
|
+
this.authorizedMessageActions.push('quote-message');
|
|
2972
|
+
}
|
|
2973
|
+
this.setEnabledActions();
|
|
2680
2974
|
}
|
|
2681
|
-
const currentOldestMessageDate = messages[0].created_at;
|
|
2682
|
-
if (!this.oldestMessageDate) {
|
|
2683
|
-
this.oldestMessageDate = currentOldestMessageDate;
|
|
2684
|
-
}
|
|
2685
|
-
else if (((_e = this.oldestMessageDate) === null || _e === void 0 ? void 0 : _e.getTime()) > currentOldestMessageDate.getTime()) {
|
|
2686
|
-
this.oldestMessageDate = currentOldestMessageDate;
|
|
2687
|
-
this.olderMassagesLoaded = true;
|
|
2688
|
-
}
|
|
2689
|
-
}), tap((messages) => {
|
|
2690
|
-
this.groupStyles = messages.map((m, i) => getGroupStyles(m, messages[i - 1], messages[i + 1]));
|
|
2691
|
-
}), tap((messages) => {
|
|
2692
|
-
var _a;
|
|
2693
|
-
return (this.lastSentMessageId = (_a = [...messages]
|
|
2694
|
-
.reverse()
|
|
2695
|
-
.find((m) => {
|
|
2696
|
-
var _a, _b, _c;
|
|
2697
|
-
return ((_a = m.user) === null || _a === void 0 ? void 0 : _a.id) === ((_c = (_b = this.chatClientService.chatClient) === null || _b === void 0 ? void 0 : _b.user) === null || _c === void 0 ? void 0 : _c.id) &&
|
|
2698
|
-
m.status !== 'sending';
|
|
2699
|
-
})) === null || _a === void 0 ? void 0 : _a.id);
|
|
2700
2975
|
}));
|
|
2701
|
-
this.imageLoadService.imageLoad$.subscribe(() => {
|
|
2976
|
+
this.subscriptions.push(this.imageLoadService.imageLoad$.subscribe(() => {
|
|
2702
2977
|
if (!this.isUserScrolledUp) {
|
|
2703
2978
|
this.scrollToBottom();
|
|
2704
2979
|
// Hacky and unreliable workaround to scroll down after loaded images move the scrollbar
|
|
@@ -2706,12 +2981,27 @@ class MessageListComponent {
|
|
|
2706
2981
|
this.scrollToBottom();
|
|
2707
2982
|
}, 300);
|
|
2708
2983
|
}
|
|
2709
|
-
});
|
|
2984
|
+
}));
|
|
2985
|
+
this.subscriptions.push(this.channelService.activeParentMessage$.subscribe((message) => {
|
|
2986
|
+
if (message &&
|
|
2987
|
+
this.parentMessage &&
|
|
2988
|
+
message.id !== this.parentMessage.id &&
|
|
2989
|
+
this.mode === 'thread') {
|
|
2990
|
+
this.resetScrollState();
|
|
2991
|
+
}
|
|
2992
|
+
this.parentMessage = message;
|
|
2993
|
+
}));
|
|
2994
|
+
}
|
|
2995
|
+
ngOnInit() {
|
|
2996
|
+
this.setMessages$();
|
|
2710
2997
|
}
|
|
2711
2998
|
ngOnChanges(changes) {
|
|
2712
2999
|
if (changes.enabledMessageActionsInput) {
|
|
2713
3000
|
this.setEnabledActions();
|
|
2714
3001
|
}
|
|
3002
|
+
if (changes.mode) {
|
|
3003
|
+
this.setMessages$();
|
|
3004
|
+
}
|
|
2715
3005
|
}
|
|
2716
3006
|
ngAfterViewChecked() {
|
|
2717
3007
|
if (this.hasNewMessages) {
|
|
@@ -2730,6 +3020,15 @@ class MessageListComponent {
|
|
|
2730
3020
|
this.containerHeight = this.scrollContainer.nativeElement.scrollHeight;
|
|
2731
3021
|
this.olderMassagesLoaded = false;
|
|
2732
3022
|
}
|
|
3023
|
+
else if (this.containerHeight !== undefined &&
|
|
3024
|
+
this.containerHeight < this.scrollContainer.nativeElement.scrollHeight &&
|
|
3025
|
+
!this.isUserScrolledUp) {
|
|
3026
|
+
this.scrollToBottom();
|
|
3027
|
+
this.containerHeight = this.scrollContainer.nativeElement.scrollHeight;
|
|
3028
|
+
}
|
|
3029
|
+
}
|
|
3030
|
+
ngOnDestroy() {
|
|
3031
|
+
this.subscriptions.forEach((s) => s.unsubscribe());
|
|
2733
3032
|
}
|
|
2734
3033
|
trackByMessageId(index, item) {
|
|
2735
3034
|
return item.id;
|
|
@@ -2739,6 +3038,7 @@ class MessageListComponent {
|
|
|
2739
3038
|
this.scrollContainer.nativeElement.scrollHeight;
|
|
2740
3039
|
}
|
|
2741
3040
|
scrolled() {
|
|
3041
|
+
var _a, _b;
|
|
2742
3042
|
this.isUserScrolledUp =
|
|
2743
3043
|
this.scrollContainer.nativeElement.scrollHeight -
|
|
2744
3044
|
(this.scrollContainer.nativeElement.scrollTop +
|
|
@@ -2747,20 +3047,36 @@ class MessageListComponent {
|
|
|
2747
3047
|
if (!this.isUserScrolledUp) {
|
|
2748
3048
|
this.unreadMessageCount = 0;
|
|
2749
3049
|
}
|
|
2750
|
-
if (this.scrollContainer.nativeElement.scrollTop
|
|
3050
|
+
if (this.scrollContainer.nativeElement.scrollTop <=
|
|
3051
|
+
(((_a = this.parentMessageElement) === null || _a === void 0 ? void 0 : _a.nativeElement.clientHeight) || 0) &&
|
|
3052
|
+
(this.prevScrollTop === undefined ||
|
|
3053
|
+
this.prevScrollTop >
|
|
3054
|
+
(((_b = this.parentMessageElement) === null || _b === void 0 ? void 0 : _b.nativeElement.clientHeight) || 0))) {
|
|
2751
3055
|
this.containerHeight = this.scrollContainer.nativeElement.scrollHeight;
|
|
2752
|
-
|
|
3056
|
+
this.mode === 'main'
|
|
3057
|
+
? void this.channelService.loadMoreMessages()
|
|
3058
|
+
: void this.channelService.loadMoreThreadReplies();
|
|
2753
3059
|
}
|
|
3060
|
+
this.prevScrollTop = this.scrollContainer.nativeElement.scrollTop;
|
|
2754
3061
|
}
|
|
2755
3062
|
preserveScrollbarPosition() {
|
|
2756
3063
|
this.scrollContainer.nativeElement.scrollTop =
|
|
2757
|
-
this.
|
|
3064
|
+
(this.prevScrollTop || 0) +
|
|
3065
|
+
(this.scrollContainer.nativeElement.scrollHeight - this.containerHeight);
|
|
2758
3066
|
}
|
|
2759
3067
|
setEnabledActions() {
|
|
2760
3068
|
this.enabledMessageActions = [];
|
|
2761
3069
|
if (!this.enabledMessageActionsInput) {
|
|
3070
|
+
this.enabledMessageActions = this.authorizedMessageActions;
|
|
2762
3071
|
return;
|
|
2763
3072
|
}
|
|
3073
|
+
this.enabledMessageActionsInput = [
|
|
3074
|
+
...this.enabledMessageActionsInput,
|
|
3075
|
+
'send-reaction',
|
|
3076
|
+
'read-events',
|
|
3077
|
+
'send-reply',
|
|
3078
|
+
'quote-message',
|
|
3079
|
+
];
|
|
2764
3080
|
this.enabledMessageActionsInput.forEach((action) => {
|
|
2765
3081
|
const isAuthorized = this.authorizedMessageActions.indexOf(action) !== -1;
|
|
2766
3082
|
if (isAuthorized) {
|
|
@@ -2768,9 +3084,61 @@ class MessageListComponent {
|
|
|
2768
3084
|
}
|
|
2769
3085
|
});
|
|
2770
3086
|
}
|
|
3087
|
+
setMessages$() {
|
|
3088
|
+
this.messages$ = (this.mode === 'main'
|
|
3089
|
+
? this.channelService.activeChannelMessages$
|
|
3090
|
+
: this.channelService.activeThreadMessages$).pipe(tap((messages) => {
|
|
3091
|
+
var _a, _b, _c, _d, _e;
|
|
3092
|
+
if (messages.length === 0) {
|
|
3093
|
+
return;
|
|
3094
|
+
}
|
|
3095
|
+
const currentLatestMessageDate = messages[messages.length - 1].created_at;
|
|
3096
|
+
if (!this.latestMessageDate ||
|
|
3097
|
+
((_a = this.latestMessageDate) === null || _a === void 0 ? void 0 : _a.getTime()) < currentLatestMessageDate.getTime()) {
|
|
3098
|
+
this.latestMessageDate = currentLatestMessageDate;
|
|
3099
|
+
this.hasNewMessages = true;
|
|
3100
|
+
this.isNewMessageSentByUser =
|
|
3101
|
+
((_b = messages[messages.length - 1].user) === null || _b === void 0 ? void 0 : _b.id) ===
|
|
3102
|
+
((_d = (_c = this.chatClientService.chatClient) === null || _c === void 0 ? void 0 : _c.user) === null || _d === void 0 ? void 0 : _d.id);
|
|
3103
|
+
if (this.isUserScrolledUp) {
|
|
3104
|
+
this.unreadMessageCount++;
|
|
3105
|
+
}
|
|
3106
|
+
}
|
|
3107
|
+
const currentOldestMessageDate = messages[0].created_at;
|
|
3108
|
+
if (!this.oldestMessageDate) {
|
|
3109
|
+
this.oldestMessageDate = currentOldestMessageDate;
|
|
3110
|
+
}
|
|
3111
|
+
else if (((_e = this.oldestMessageDate) === null || _e === void 0 ? void 0 : _e.getTime()) > currentOldestMessageDate.getTime()) {
|
|
3112
|
+
this.oldestMessageDate = currentOldestMessageDate;
|
|
3113
|
+
this.olderMassagesLoaded = true;
|
|
3114
|
+
}
|
|
3115
|
+
}), tap((messages) => {
|
|
3116
|
+
this.groupStyles = messages.map((m, i) => getGroupStyles(m, messages[i - 1], messages[i + 1]));
|
|
3117
|
+
}), tap((messages) => {
|
|
3118
|
+
var _a;
|
|
3119
|
+
return (this.lastSentMessageId = (_a = [...messages]
|
|
3120
|
+
.reverse()
|
|
3121
|
+
.find((m) => {
|
|
3122
|
+
var _a, _b, _c;
|
|
3123
|
+
return ((_a = m.user) === null || _a === void 0 ? void 0 : _a.id) === ((_c = (_b = this.chatClientService.chatClient) === null || _b === void 0 ? void 0 : _b.user) === null || _c === void 0 ? void 0 : _c.id) &&
|
|
3124
|
+
m.status !== 'sending';
|
|
3125
|
+
})) === null || _a === void 0 ? void 0 : _a.id);
|
|
3126
|
+
}));
|
|
3127
|
+
}
|
|
3128
|
+
resetScrollState() {
|
|
3129
|
+
this.latestMessageDate = undefined;
|
|
3130
|
+
this.hasNewMessages = true;
|
|
3131
|
+
this.isUserScrolledUp = false;
|
|
3132
|
+
this.containerHeight = undefined;
|
|
3133
|
+
this.olderMassagesLoaded = false;
|
|
3134
|
+
this.oldestMessageDate = undefined;
|
|
3135
|
+
this.unreadMessageCount = 0;
|
|
3136
|
+
this.prevScrollTop = undefined;
|
|
3137
|
+
this.isNewMessageSentByUser = undefined;
|
|
3138
|
+
}
|
|
2771
3139
|
}
|
|
2772
3140
|
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 });
|
|
2773
|
-
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"] }, host: { properties: { "class": "this.class" } }, viewQueries: [{ propertyName: "scrollContainer", first: true, predicate: ["scrollContainer"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div\n #scrollContainer\n data-testid=\"scroll-container\"\n class=\"str-chat__list\"\n (scroll)=\"scrolled()\"\n>\n <div class=\"str-chat__reverse-infinite-scroll\">\n <ul class=\"str-chat__ul\">\n <li\n data-testclass=\"message\"\n *ngFor=\"\n let message of messages$ | async;\n let i = index;\n trackBy: trackByMessageId\n \"\n class=\"str-chat__li str-chat__li--{{ groupStyles[i] }}\"\n >\n <ng-container
|
|
3141
|
+
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: i1.TranslateDirective, selector: "[translate],[ngx-translate]", inputs: ["translate", "translateParams"] }, { type: i6.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }], pipes: { "async": i6.AsyncPipe } });
|
|
2774
3142
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: MessageListComponent, decorators: [{
|
|
2775
3143
|
type: Component,
|
|
2776
3144
|
args: [{
|
|
@@ -2789,12 +3157,49 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImpor
|
|
|
2789
3157
|
}], enabledMessageActionsInput: [{
|
|
2790
3158
|
type: Input,
|
|
2791
3159
|
args: ['enabledMessageActions']
|
|
3160
|
+
}], mode: [{
|
|
3161
|
+
type: Input
|
|
2792
3162
|
}], class: [{
|
|
2793
3163
|
type: HostBinding,
|
|
2794
3164
|
args: ['class']
|
|
2795
3165
|
}], scrollContainer: [{
|
|
2796
3166
|
type: ViewChild,
|
|
2797
3167
|
args: ['scrollContainer']
|
|
3168
|
+
}], parentMessageElement: [{
|
|
3169
|
+
type: ViewChild,
|
|
3170
|
+
args: ['parentMessageElement']
|
|
3171
|
+
}] } });
|
|
3172
|
+
|
|
3173
|
+
class ThreadComponent {
|
|
3174
|
+
constructor(channelService) {
|
|
3175
|
+
this.channelService = channelService;
|
|
3176
|
+
this.class = 'str-chat__thread';
|
|
3177
|
+
this.subscriptions = [];
|
|
3178
|
+
this.subscriptions.push(this.channelService.activeParentMessage$.subscribe((parentMessage) => (this.parentMessage = parentMessage)));
|
|
3179
|
+
}
|
|
3180
|
+
ngOnDestroy() {
|
|
3181
|
+
this.subscriptions.forEach((s) => s.unsubscribe());
|
|
3182
|
+
}
|
|
3183
|
+
get replyCountParam() {
|
|
3184
|
+
var _a;
|
|
3185
|
+
return { replyCount: (_a = this.parentMessage) === null || _a === void 0 ? void 0 : _a.reply_count };
|
|
3186
|
+
}
|
|
3187
|
+
closeThread() {
|
|
3188
|
+
void this.channelService.setAsActiveParentMessage(undefined);
|
|
3189
|
+
}
|
|
3190
|
+
}
|
|
3191
|
+
ThreadComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: ThreadComponent, deps: [{ token: ChannelService }], target: i0.ɵɵFactoryTarget.Component });
|
|
3192
|
+
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: i1.TranslateDirective, selector: "[translate],[ngx-translate]", inputs: ["translate", "translateParams"] }], pipes: { "translate": i1.TranslatePipe } });
|
|
3193
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: ThreadComponent, decorators: [{
|
|
3194
|
+
type: Component,
|
|
3195
|
+
args: [{
|
|
3196
|
+
selector: 'stream-thread',
|
|
3197
|
+
templateUrl: './thread.component.html',
|
|
3198
|
+
styles: [],
|
|
3199
|
+
}]
|
|
3200
|
+
}], ctorParameters: function () { return [{ type: ChannelService }]; }, propDecorators: { class: [{
|
|
3201
|
+
type: HostBinding,
|
|
3202
|
+
args: ['class']
|
|
2798
3203
|
}] } });
|
|
2799
3204
|
|
|
2800
3205
|
class StreamAvatarModule {
|
|
@@ -2830,7 +3235,8 @@ StreamChatModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "12.0.0", versio
|
|
|
2830
3235
|
NotificationListComponent,
|
|
2831
3236
|
AttachmentPreviewListComponent,
|
|
2832
3237
|
ModalComponent,
|
|
2833
|
-
TextareaDirective
|
|
3238
|
+
TextareaDirective,
|
|
3239
|
+
ThreadComponent], imports: [CommonModule, TranslateModule, StreamAvatarModule], exports: [ChannelComponent,
|
|
2834
3240
|
ChannelHeaderComponent,
|
|
2835
3241
|
ChannelListComponent,
|
|
2836
3242
|
ChannelPreviewComponent,
|
|
@@ -2846,7 +3252,8 @@ StreamChatModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "12.0.0", versio
|
|
|
2846
3252
|
NotificationListComponent,
|
|
2847
3253
|
AttachmentPreviewListComponent,
|
|
2848
3254
|
ModalComponent,
|
|
2849
|
-
StreamAvatarModule
|
|
3255
|
+
StreamAvatarModule,
|
|
3256
|
+
ThreadComponent] });
|
|
2850
3257
|
StreamChatModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: StreamChatModule, imports: [[CommonModule, TranslateModule, StreamAvatarModule], StreamAvatarModule] });
|
|
2851
3258
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: StreamChatModule, decorators: [{
|
|
2852
3259
|
type: NgModule,
|
|
@@ -2869,6 +3276,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImpor
|
|
|
2869
3276
|
AttachmentPreviewListComponent,
|
|
2870
3277
|
ModalComponent,
|
|
2871
3278
|
TextareaDirective,
|
|
3279
|
+
ThreadComponent,
|
|
2872
3280
|
],
|
|
2873
3281
|
imports: [CommonModule, TranslateModule, StreamAvatarModule],
|
|
2874
3282
|
exports: [
|
|
@@ -2889,6 +3297,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImpor
|
|
|
2889
3297
|
AttachmentPreviewListComponent,
|
|
2890
3298
|
ModalComponent,
|
|
2891
3299
|
StreamAvatarModule,
|
|
3300
|
+
ThreadComponent,
|
|
2892
3301
|
],
|
|
2893
3302
|
}]
|
|
2894
3303
|
}] });
|
|
@@ -2951,5 +3360,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImpor
|
|
|
2951
3360
|
* Generated bundle index. Do not edit.
|
|
2952
3361
|
*/
|
|
2953
3362
|
|
|
2954
|
-
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, TransliterationService, createMessagePreview, getDeviceWidth, getGroupStyles, getReadBy, getReadByText, isImageAttachment, isImageFile, parseDate, textareaInjectionToken };
|
|
3363
|
+
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 };
|
|
2955
3364
|
//# sourceMappingURL=stream-chat-angular.js.map
|