stream-chat-angular 2.10.0 → 2.12.2
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 +670 -337
- package/bundles/stream-chat-angular.umd.js.map +1 -1
- package/esm2015/assets/i18n/en.js +3 -1
- package/esm2015/assets/version.js +2 -2
- package/esm2015/lib/channel/channel.component.js +3 -2
- package/esm2015/lib/channel.service.js +170 -40
- 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 +7 -4
- package/esm2015/lib/message-input/message-input.component.js +61 -13
- package/esm2015/lib/message-list/message-list.component.js +104 -53
- package/esm2015/lib/message-preview.js +4 -2
- package/esm2015/lib/message-reactions/message-reactions.component.js +2 -2
- package/esm2015/lib/stream-chat.module.js +8 -3
- package/esm2015/lib/thread/thread.component.js +37 -0
- package/esm2015/public-api.js +2 -1
- package/fesm2015/stream-chat-angular.js +541 -246
- package/fesm2015/stream-chat-angular.js.map +1 -1
- package/lib/channel/channel.component.d.ts +2 -1
- package/lib/channel.service.d.ts +21 -7
- package/lib/icon/icon.component.d.ts +1 -1
- package/lib/message/message.component.d.ts +16 -6
- package/lib/message-input/message-input.component.d.ts +7 -1
- package/lib/message-list/message-list.component.d.ts +12 -3
- 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/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
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.2';
|
|
20
20
|
|
|
21
21
|
class NotificationService {
|
|
22
22
|
constructor() {
|
|
@@ -149,7 +149,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImpor
|
|
|
149
149
|
}]
|
|
150
150
|
}], ctorParameters: function () { return [{ type: i0.NgZone }, { type: NotificationService }]; } });
|
|
151
151
|
|
|
152
|
-
const createMessagePreview = (user, text, attachments, mentionedUsers) => {
|
|
152
|
+
const createMessagePreview = (user, text, attachments = [], mentionedUsers = [], parentId = undefined, quotedMessageId = undefined) => {
|
|
153
153
|
const clientSideId = `${user.id}-${v4()}`;
|
|
154
154
|
return {
|
|
155
155
|
__html: text,
|
|
@@ -163,6 +163,8 @@ const createMessagePreview = (user, text, attachments, mentionedUsers) => {
|
|
|
163
163
|
user,
|
|
164
164
|
attachments,
|
|
165
165
|
mentioned_users: mentionedUsers,
|
|
166
|
+
parent_id: parentId,
|
|
167
|
+
quoted_message_id: quotedMessageId,
|
|
166
168
|
};
|
|
167
169
|
};
|
|
168
170
|
|
|
@@ -188,31 +190,52 @@ class ChannelService {
|
|
|
188
190
|
this.activeChannelMessagesSubject = new BehaviorSubject([]);
|
|
189
191
|
this.hasMoreChannelsSubject = new ReplaySubject(1);
|
|
190
192
|
this.activeChannelSubscriptions = [];
|
|
193
|
+
this.activeParentMessageIdSubject = new BehaviorSubject(undefined);
|
|
194
|
+
this.activeThreadMessagesSubject = new BehaviorSubject([]);
|
|
195
|
+
this.messagePageSize = 25;
|
|
196
|
+
this.messageToQuoteSubject = new BehaviorSubject(undefined);
|
|
191
197
|
this.channelListSetter = (channels) => {
|
|
192
198
|
this.channelsSubject.next(channels);
|
|
193
199
|
};
|
|
194
200
|
this.messageListSetter = (messages) => {
|
|
195
201
|
this.activeChannelMessagesSubject.next(messages);
|
|
196
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
|
+
};
|
|
197
209
|
this.channels$ = this.channelsSubject.asObservable();
|
|
198
210
|
this.activeChannel$ = this.activeChannelSubject.asObservable();
|
|
199
211
|
this.activeChannelMessages$ = this.activeChannelMessagesSubject.pipe(map((messages) => {
|
|
200
212
|
const channel = this.activeChannelSubject.getValue();
|
|
201
|
-
return messages.map((message) =>
|
|
202
|
-
if (this.isStreamMessage(message) &&
|
|
203
|
-
this.isFormatMessageResponse(message)) {
|
|
204
|
-
return message;
|
|
205
|
-
}
|
|
206
|
-
else if (this.isFormatMessageResponse(message)) {
|
|
207
|
-
return Object.assign(Object.assign({}, message), { readBy: getReadBy(message, channel) });
|
|
208
|
-
}
|
|
209
|
-
else {
|
|
210
|
-
const formatMessage = this.formatMessage(message);
|
|
211
|
-
return Object.assign(Object.assign({}, formatMessage), { readBy: getReadBy(formatMessage, channel) });
|
|
212
|
-
}
|
|
213
|
-
});
|
|
213
|
+
return messages.map((message) => this.transformToStreamMessage(message, channel));
|
|
214
214
|
}));
|
|
215
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
|
+
});
|
|
216
239
|
}
|
|
217
240
|
setAsActiveChannel(channel) {
|
|
218
241
|
const prevActiveChannel = this.activeChannelSubject.getValue();
|
|
@@ -226,25 +249,66 @@ class ChannelService {
|
|
|
226
249
|
void channel.markRead();
|
|
227
250
|
}
|
|
228
251
|
this.activeChannelMessagesSubject.next([...channel.state.messages]);
|
|
252
|
+
this.activeParentMessageIdSubject.next(undefined);
|
|
253
|
+
this.activeThreadMessagesSubject.next([]);
|
|
254
|
+
this.messageToQuoteSubject.next(undefined);
|
|
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
|
+
});
|
|
229
276
|
}
|
|
277
|
+
// load more thread replies
|
|
230
278
|
loadMoreMessages() {
|
|
231
|
-
var _a, _b, _c, _d;
|
|
279
|
+
var _a, _b, _c, _d, _e;
|
|
232
280
|
return __awaiter(this, void 0, void 0, function* () {
|
|
233
281
|
const activeChnannel = this.activeChannelSubject.getValue();
|
|
234
282
|
const lastMessageId = (_a = this.activeChannelMessagesSubject.getValue()[0]) === null || _a === void 0 ? void 0 : _a.id;
|
|
235
283
|
yield (activeChnannel === null || activeChnannel === void 0 ? void 0 : activeChnannel.query({
|
|
236
|
-
messages: { limit:
|
|
284
|
+
messages: { limit: (_b = this.options) === null || _b === void 0 ? void 0 : _b.message_limit, id_lt: lastMessageId },
|
|
237
285
|
members: { limit: 0 },
|
|
238
286
|
watchers: { limit: 0 },
|
|
239
287
|
}));
|
|
240
|
-
if (((
|
|
241
|
-
((
|
|
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)) {
|
|
242
290
|
this.activeChannelMessagesSubject.next([
|
|
243
291
|
...activeChnannel.state.messages,
|
|
244
292
|
]);
|
|
245
293
|
}
|
|
246
294
|
});
|
|
247
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
|
+
}
|
|
248
312
|
init(filters, sort, options) {
|
|
249
313
|
return __awaiter(this, void 0, void 0, function* () {
|
|
250
314
|
this.filters = filters;
|
|
@@ -254,7 +318,7 @@ class ChannelService {
|
|
|
254
318
|
state: true,
|
|
255
319
|
presence: true,
|
|
256
320
|
watch: true,
|
|
257
|
-
message_limit:
|
|
321
|
+
message_limit: this.messagePageSize,
|
|
258
322
|
};
|
|
259
323
|
this.sort = sort || { last_message_at: -1, updated_at: -1 };
|
|
260
324
|
yield this.queryChannels();
|
|
@@ -264,7 +328,10 @@ class ChannelService {
|
|
|
264
328
|
reset() {
|
|
265
329
|
this.activeChannelMessagesSubject.next([]);
|
|
266
330
|
this.activeChannelSubject.next(undefined);
|
|
331
|
+
this.activeParentMessageIdSubject.next(undefined);
|
|
332
|
+
this.activeThreadMessagesSubject.next([]);
|
|
267
333
|
this.channelsSubject.next(undefined);
|
|
334
|
+
this.selectMessageToQuote(undefined);
|
|
268
335
|
}
|
|
269
336
|
loadMoreChannels() {
|
|
270
337
|
return __awaiter(this, void 0, void 0, function* () {
|
|
@@ -287,9 +354,9 @@ class ChannelService {
|
|
|
287
354
|
.getValue()) === null || _a === void 0 ? void 0 : _a.deleteReaction(messageId, reactionType));
|
|
288
355
|
});
|
|
289
356
|
}
|
|
290
|
-
sendMessage(text, attachments = [], mentionedUsers = []) {
|
|
357
|
+
sendMessage(text, attachments = [], mentionedUsers = [], parentId = undefined, quotedMessageId = undefined) {
|
|
291
358
|
return __awaiter(this, void 0, void 0, function* () {
|
|
292
|
-
const preview = createMessagePreview(this.chatClientService.chatClient.user, text, attachments, mentionedUsers);
|
|
359
|
+
const preview = createMessagePreview(this.chatClientService.chatClient.user, text, attachments, mentionedUsers, parentId, quotedMessageId);
|
|
293
360
|
const channel = this.activeChannelSubject.getValue();
|
|
294
361
|
preview.readBy = [];
|
|
295
362
|
channel.state.addMessageSorted(preview, true);
|
|
@@ -373,29 +440,57 @@ class ChannelService {
|
|
|
373
440
|
const response = yield channel.sendAction(messageId, formData);
|
|
374
441
|
if (response === null || response === void 0 ? void 0 : response.message) {
|
|
375
442
|
channel.state.addMessageSorted(Object.assign(Object.assign({}, response.message), { status: 'received' }));
|
|
376
|
-
|
|
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]);
|
|
377
449
|
}
|
|
378
450
|
else {
|
|
379
451
|
channel.state.removeMessage({ id: messageId });
|
|
380
|
-
this.activeChannelMessagesSubject
|
|
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
|
+
}
|
|
381
462
|
}
|
|
382
463
|
});
|
|
383
464
|
}
|
|
465
|
+
selectMessageToQuote(message) {
|
|
466
|
+
this.messageToQuoteSubject.next(message);
|
|
467
|
+
}
|
|
384
468
|
sendMessageRequest(preview) {
|
|
385
469
|
var _a;
|
|
386
470
|
return __awaiter(this, void 0, void 0, function* () {
|
|
387
471
|
const channel = this.activeChannelSubject.getValue();
|
|
388
|
-
|
|
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]);
|
|
389
478
|
try {
|
|
390
479
|
const response = yield channel.sendMessage({
|
|
391
480
|
text: preview.text,
|
|
392
481
|
attachments: preview.attachments,
|
|
393
482
|
mentioned_users: (_a = preview.mentioned_users) === null || _a === void 0 ? void 0 : _a.map((u) => u.id),
|
|
394
483
|
id: preview.id,
|
|
484
|
+
parent_id: preview.parent_id,
|
|
485
|
+
quoted_message_id: preview.quoted_message_id,
|
|
395
486
|
});
|
|
396
487
|
if (response === null || response === void 0 ? void 0 : response.message) {
|
|
397
488
|
channel.state.addMessageSorted(Object.assign(Object.assign({}, response.message), { status: 'received' }), true);
|
|
398
|
-
|
|
489
|
+
isThreadReply
|
|
490
|
+
? this.activeThreadMessagesSubject.next([
|
|
491
|
+
...channel.state.threads[preview.parent_id],
|
|
492
|
+
])
|
|
493
|
+
: this.activeChannelMessagesSubject.next([...channel.state.messages]);
|
|
399
494
|
}
|
|
400
495
|
}
|
|
401
496
|
catch (error) {
|
|
@@ -404,7 +499,11 @@ class ChannelService {
|
|
|
404
499
|
? JSON.parse(stringError)
|
|
405
500
|
: {};
|
|
406
501
|
channel.state.addMessageSorted(Object.assign(Object.assign({}, preview), { errorStatusCode: parsedError.status || undefined, status: 'failed' }), true);
|
|
407
|
-
|
|
502
|
+
isThreadReply
|
|
503
|
+
? this.activeThreadMessagesSubject.next([
|
|
504
|
+
...channel.state.threads[preview.parent_id],
|
|
505
|
+
])
|
|
506
|
+
: this.activeChannelMessagesSubject.next([...channel.state.messages]);
|
|
408
507
|
}
|
|
409
508
|
});
|
|
410
509
|
}
|
|
@@ -482,9 +581,15 @@ class ChannelService {
|
|
|
482
581
|
}
|
|
483
582
|
}
|
|
484
583
|
watchForActiveChannelEvents(channel) {
|
|
485
|
-
this.activeChannelSubscriptions.push(channel.on('message.new', () => {
|
|
584
|
+
this.activeChannelSubscriptions.push(channel.on('message.new', (event) => {
|
|
486
585
|
this.ngZone.run(() => {
|
|
487
|
-
|
|
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
|
+
]);
|
|
488
593
|
this.activeChannel$.pipe(first()).subscribe((c) => {
|
|
489
594
|
if (this.canSendReadEvents) {
|
|
490
595
|
void (c === null || c === void 0 ? void 0 : c.markRead());
|
|
@@ -513,19 +618,27 @@ class ChannelService {
|
|
|
513
618
|
}
|
|
514
619
|
messageUpdated(event) {
|
|
515
620
|
this.ngZone.run(() => {
|
|
516
|
-
const
|
|
621
|
+
const isThreadReply = event.message && event.message.parent_id;
|
|
622
|
+
const messages = isThreadReply
|
|
623
|
+
? this.activeThreadMessagesSubject.getValue()
|
|
624
|
+
: this.activeChannelMessagesSubject.getValue();
|
|
517
625
|
const messageIndex = messages.findIndex((m) => { var _a; return m.id === ((_a = event.message) === null || _a === void 0 ? void 0 : _a.id); });
|
|
518
626
|
if (messageIndex !== -1 && event.message) {
|
|
519
627
|
messages[messageIndex] = event.message;
|
|
520
|
-
|
|
628
|
+
isThreadReply
|
|
629
|
+
? this.activeThreadMessagesSubject.next([...messages])
|
|
630
|
+
: this.activeChannelMessagesSubject.next([...messages]);
|
|
521
631
|
}
|
|
522
632
|
});
|
|
523
633
|
}
|
|
524
634
|
messageReactionEventReceived(e) {
|
|
525
635
|
this.ngZone.run(() => {
|
|
526
636
|
var _a, _b, _c, _d;
|
|
637
|
+
const isThreadMessage = e.message && e.message.parent_id;
|
|
527
638
|
let messages;
|
|
528
|
-
|
|
639
|
+
(isThreadMessage
|
|
640
|
+
? this.activeThreadMessages$
|
|
641
|
+
: this.activeChannelMessages$)
|
|
529
642
|
.pipe(first())
|
|
530
643
|
.subscribe((m) => (messages = m));
|
|
531
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); });
|
|
@@ -536,7 +649,9 @@ class ChannelService {
|
|
|
536
649
|
message.reaction_scores = Object.assign({}, (_b = e.message) === null || _b === void 0 ? void 0 : _b.reaction_scores);
|
|
537
650
|
message.latest_reactions = [...(((_c = e.message) === null || _c === void 0 ? void 0 : _c.latest_reactions) || [])];
|
|
538
651
|
message.own_reactions = [...(((_d = e.message) === null || _d === void 0 ? void 0 : _d.own_reactions) || [])];
|
|
539
|
-
|
|
652
|
+
isThreadMessage
|
|
653
|
+
? this.activeThreadMessagesSubject.next([...messages])
|
|
654
|
+
: this.activeChannelMessagesSubject.next([...messages]);
|
|
540
655
|
});
|
|
541
656
|
}
|
|
542
657
|
formatMessage(message) {
|
|
@@ -584,7 +699,7 @@ class ChannelService {
|
|
|
584
699
|
case 'message.new': {
|
|
585
700
|
this.ngZone.run(() => {
|
|
586
701
|
if (this.customNewMessageHandler) {
|
|
587
|
-
this.customNewMessageHandler(event, channel, this.channelListSetter, this.messageListSetter);
|
|
702
|
+
this.customNewMessageHandler(event, channel, this.channelListSetter, this.messageListSetter, this.threadListSetter, this.parentMessageSetter);
|
|
588
703
|
}
|
|
589
704
|
else {
|
|
590
705
|
this.handleNewMessage(event, channel);
|
|
@@ -595,7 +710,7 @@ class ChannelService {
|
|
|
595
710
|
case 'channel.hidden': {
|
|
596
711
|
this.ngZone.run(() => {
|
|
597
712
|
if (this.customChannelHiddenHandler) {
|
|
598
|
-
this.customChannelHiddenHandler(event, channel, this.channelListSetter, this.messageListSetter);
|
|
713
|
+
this.customChannelHiddenHandler(event, channel, this.channelListSetter, this.messageListSetter, this.threadListSetter, this.parentMessageSetter);
|
|
599
714
|
}
|
|
600
715
|
else {
|
|
601
716
|
this.handleChannelHidden(event);
|
|
@@ -606,7 +721,7 @@ class ChannelService {
|
|
|
606
721
|
case 'channel.deleted': {
|
|
607
722
|
this.ngZone.run(() => {
|
|
608
723
|
if (this.customChannelDeletedHandler) {
|
|
609
|
-
this.customChannelDeletedHandler(event, channel, this.channelListSetter, this.messageListSetter);
|
|
724
|
+
this.customChannelDeletedHandler(event, channel, this.channelListSetter, this.messageListSetter, this.threadListSetter, this.parentMessageSetter);
|
|
610
725
|
}
|
|
611
726
|
else {
|
|
612
727
|
this.handleChannelDeleted(event);
|
|
@@ -617,7 +732,7 @@ class ChannelService {
|
|
|
617
732
|
case 'channel.visible': {
|
|
618
733
|
this.ngZone.run(() => {
|
|
619
734
|
if (this.customChannelVisibleHandler) {
|
|
620
|
-
this.customChannelVisibleHandler(event, channel, this.channelListSetter, this.messageListSetter);
|
|
735
|
+
this.customChannelVisibleHandler(event, channel, this.channelListSetter, this.messageListSetter, this.threadListSetter, this.parentMessageSetter);
|
|
621
736
|
}
|
|
622
737
|
else {
|
|
623
738
|
this.handleChannelVisible(event, channel);
|
|
@@ -628,7 +743,7 @@ class ChannelService {
|
|
|
628
743
|
case 'channel.updated': {
|
|
629
744
|
this.ngZone.run(() => {
|
|
630
745
|
if (this.customChannelUpdatedHandler) {
|
|
631
|
-
this.customChannelUpdatedHandler(event, channel, this.channelListSetter, this.messageListSetter);
|
|
746
|
+
this.customChannelUpdatedHandler(event, channel, this.channelListSetter, this.messageListSetter, this.threadListSetter, this.parentMessageSetter);
|
|
632
747
|
}
|
|
633
748
|
else {
|
|
634
749
|
this.handleChannelUpdate(event);
|
|
@@ -639,7 +754,7 @@ class ChannelService {
|
|
|
639
754
|
case 'channel.truncated': {
|
|
640
755
|
this.ngZone.run(() => {
|
|
641
756
|
if (this.customChannelTruncatedHandler) {
|
|
642
|
-
this.customChannelTruncatedHandler(event, channel, this.channelListSetter, this.messageListSetter);
|
|
757
|
+
this.customChannelTruncatedHandler(event, channel, this.channelListSetter, this.messageListSetter, this.threadListSetter, this.parentMessageSetter);
|
|
643
758
|
}
|
|
644
759
|
else {
|
|
645
760
|
this.handleChannelTruncate(event);
|
|
@@ -679,6 +794,7 @@ class ChannelService {
|
|
|
679
794
|
}
|
|
680
795
|
}
|
|
681
796
|
}
|
|
797
|
+
// truncate active thread as well
|
|
682
798
|
handleChannelTruncate(event) {
|
|
683
799
|
var _a, _b;
|
|
684
800
|
const channelIndex = this.channels.findIndex((c) => c.cid === event.channel.cid);
|
|
@@ -690,6 +806,8 @@ class ChannelService {
|
|
|
690
806
|
channel.state.messages = [];
|
|
691
807
|
this.activeChannelSubject.next(channel);
|
|
692
808
|
this.activeChannelMessagesSubject.next([]);
|
|
809
|
+
this.activeParentMessageIdSubject.next(undefined);
|
|
810
|
+
this.activeThreadMessagesSubject.next([]);
|
|
693
811
|
}
|
|
694
812
|
}
|
|
695
813
|
}
|
|
@@ -705,6 +823,20 @@ class ChannelService {
|
|
|
705
823
|
const capabilites = (_a = channel.data) === null || _a === void 0 ? void 0 : _a.own_capabilities;
|
|
706
824
|
return capabilites.indexOf('read-events') !== -1;
|
|
707
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
|
+
}
|
|
708
840
|
}
|
|
709
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 });
|
|
710
842
|
ChannelService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: ChannelService, providedIn: 'root' });
|
|
@@ -1017,6 +1149,7 @@ const en = {
|
|
|
1017
1149
|
Flag: 'Flag',
|
|
1018
1150
|
'Message Failed': 'Message Failed',
|
|
1019
1151
|
'Message Failed · Unauthorized': 'Message Failed · Unauthorized',
|
|
1152
|
+
'Message Failed · Click to try again': 'Message Failed · Click to try again',
|
|
1020
1153
|
'Message deleted': 'Message deleted',
|
|
1021
1154
|
'Message has been successfully flagged': 'Message has been successfully flagged',
|
|
1022
1155
|
'Message pinned': 'Message pinned',
|
|
@@ -1067,6 +1200,7 @@ const en = {
|
|
|
1067
1200
|
test: 'success',
|
|
1068
1201
|
'Sending links is not allowed in this conversation': 'Sending links is not allowed in this conversation',
|
|
1069
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",
|
|
1070
1204
|
'Unsupported file type: {{type}}': 'Unsupported file type: {{type}}',
|
|
1071
1205
|
},
|
|
1072
1206
|
};
|
|
@@ -1082,14 +1216,14 @@ class StreamI18nService {
|
|
|
1082
1216
|
this.translteService.setTranslation(lang, { streamChat: Object.assign(Object.assign({}, en.streamChat), overrides) }, true);
|
|
1083
1217
|
}
|
|
1084
1218
|
}
|
|
1085
|
-
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 });
|
|
1086
1220
|
StreamI18nService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: StreamI18nService, providedIn: 'root' });
|
|
1087
1221
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: StreamI18nService, decorators: [{
|
|
1088
1222
|
type: Injectable,
|
|
1089
1223
|
args: [{
|
|
1090
1224
|
providedIn: 'root',
|
|
1091
1225
|
}]
|
|
1092
|
-
}], ctorParameters: function () { return [{ type:
|
|
1226
|
+
}], ctorParameters: function () { return [{ type: i1.TranslateService }]; } });
|
|
1093
1227
|
|
|
1094
1228
|
class AvatarComponent {
|
|
1095
1229
|
constructor() {
|
|
@@ -1123,7 +1257,7 @@ class IconComponent {
|
|
|
1123
1257
|
constructor() { }
|
|
1124
1258
|
}
|
|
1125
1259
|
IconComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: IconComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1126
|
-
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: i6.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { 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"] }] });
|
|
1127
1261
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: IconComponent, decorators: [{
|
|
1128
1262
|
type: Component,
|
|
1129
1263
|
args: [{
|
|
@@ -1261,6 +1395,90 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImpor
|
|
|
1261
1395
|
}]
|
|
1262
1396
|
}], ctorParameters: function () { return []; } });
|
|
1263
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
|
+
|
|
1264
1482
|
class AttachmentPreviewListComponent {
|
|
1265
1483
|
constructor(attachmentService) {
|
|
1266
1484
|
this.attachmentService = attachmentService;
|
|
@@ -1281,7 +1499,7 @@ class AttachmentPreviewListComponent {
|
|
|
1281
1499
|
}
|
|
1282
1500
|
}
|
|
1283
1501
|
AttachmentPreviewListComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: AttachmentPreviewListComponent, deps: [{ token: AttachmentService }], target: i0.ɵɵFactoryTarget.Component });
|
|
1284
|
-
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:
|
|
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 } });
|
|
1285
1503
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: AttachmentPreviewListComponent, decorators: [{
|
|
1286
1504
|
type: Component,
|
|
1287
1505
|
args: [{
|
|
@@ -1301,6 +1519,7 @@ class MessageInputComponent {
|
|
|
1301
1519
|
this.componentFactoryResolver = componentFactoryResolver;
|
|
1302
1520
|
this.cdRef = cdRef;
|
|
1303
1521
|
this.chatClient = chatClient;
|
|
1522
|
+
this.mode = 'main';
|
|
1304
1523
|
this.messageUpdate = new EventEmitter();
|
|
1305
1524
|
this.textareaValue = '';
|
|
1306
1525
|
this.mentionedUsers = [];
|
|
@@ -1321,14 +1540,19 @@ class MessageInputComponent {
|
|
|
1321
1540
|
this.isFileUploadAuthorized =
|
|
1322
1541
|
capabilities.indexOf('upload-file') !== -1;
|
|
1323
1542
|
this.canSendLinks = capabilities.indexOf('send-links') !== -1;
|
|
1324
|
-
this.
|
|
1325
|
-
|
|
1326
|
-
this.cdRef.detectChanges();
|
|
1327
|
-
this.initTextarea();
|
|
1328
|
-
}
|
|
1543
|
+
this.channel = channel;
|
|
1544
|
+
this.setCanSendMessages();
|
|
1329
1545
|
}
|
|
1330
1546
|
}));
|
|
1331
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
|
+
}));
|
|
1332
1556
|
this.attachmentUploads$ = this.attachmentService.attachmentUploads$;
|
|
1333
1557
|
this.isFileUploadEnabled = this.configService.isFileUploadEnabled;
|
|
1334
1558
|
this.acceptedFileTypes = this.configService.acceptedFileTypes;
|
|
@@ -1377,11 +1601,15 @@ class MessageInputComponent {
|
|
|
1377
1601
|
if (changes.mentionScope) {
|
|
1378
1602
|
this.configService.mentionScope = this.mentionScope;
|
|
1379
1603
|
}
|
|
1604
|
+
if (changes.mode) {
|
|
1605
|
+
this.setCanSendMessages();
|
|
1606
|
+
}
|
|
1380
1607
|
}
|
|
1381
1608
|
ngOnDestroy() {
|
|
1382
1609
|
this.subscriptions.forEach((s) => s.unsubscribe());
|
|
1383
1610
|
}
|
|
1384
1611
|
messageSent() {
|
|
1612
|
+
var _a;
|
|
1385
1613
|
return __awaiter(this, void 0, void 0, function* () {
|
|
1386
1614
|
let attachmentUploadInProgressCounter;
|
|
1387
1615
|
this.attachmentService.attachmentUploadInProgressCounter$
|
|
@@ -1406,10 +1634,16 @@ class MessageInputComponent {
|
|
|
1406
1634
|
if (!this.isUpdate) {
|
|
1407
1635
|
this.textareaValue = '';
|
|
1408
1636
|
}
|
|
1637
|
+
let parentMessageId = undefined;
|
|
1638
|
+
if (this.mode === 'thread') {
|
|
1639
|
+
this.channelService.activeParentMessageId$
|
|
1640
|
+
.pipe(first())
|
|
1641
|
+
.subscribe((id) => (parentMessageId = id));
|
|
1642
|
+
}
|
|
1409
1643
|
try {
|
|
1410
1644
|
yield (this.isUpdate
|
|
1411
1645
|
? this.channelService.updateMessage(Object.assign(Object.assign({}, this.message), { text: text, attachments: attachments }))
|
|
1412
|
-
: 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));
|
|
1413
1647
|
this.messageUpdate.emit();
|
|
1414
1648
|
if (!this.isUpdate) {
|
|
1415
1649
|
this.attachmentService.resetAttachmentUploads();
|
|
@@ -1420,6 +1654,9 @@ class MessageInputComponent {
|
|
|
1420
1654
|
this.notificationService.addTemporaryNotification('streamChat.Edit message request failed');
|
|
1421
1655
|
}
|
|
1422
1656
|
}
|
|
1657
|
+
if (this.quotedMessage) {
|
|
1658
|
+
this.deselectMessageToQuote();
|
|
1659
|
+
}
|
|
1423
1660
|
});
|
|
1424
1661
|
}
|
|
1425
1662
|
get containsLinks() {
|
|
@@ -1429,6 +1666,13 @@ class MessageInputComponent {
|
|
|
1429
1666
|
var _a;
|
|
1430
1667
|
return this.acceptedFileTypes ? (_a = this.acceptedFileTypes) === null || _a === void 0 ? void 0 : _a.join(',') : '';
|
|
1431
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
|
+
}
|
|
1432
1676
|
filesSelected(fileList) {
|
|
1433
1677
|
return __awaiter(this, void 0, void 0, function* () {
|
|
1434
1678
|
if (!(yield this.areAttachemntsValid(fileList))) {
|
|
@@ -1438,6 +1682,9 @@ class MessageInputComponent {
|
|
|
1438
1682
|
this.clearFileInput();
|
|
1439
1683
|
});
|
|
1440
1684
|
}
|
|
1685
|
+
deselectMessageToQuote() {
|
|
1686
|
+
this.channelService.selectMessageToQuote(undefined);
|
|
1687
|
+
}
|
|
1441
1688
|
clearFileInput() {
|
|
1442
1689
|
this.fileInput.nativeElement.value = '';
|
|
1443
1690
|
}
|
|
@@ -1503,9 +1750,24 @@ class MessageInputComponent {
|
|
|
1503
1750
|
return isValid;
|
|
1504
1751
|
});
|
|
1505
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
|
+
}
|
|
1506
1768
|
}
|
|
1507
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 });
|
|
1508
|
-
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", 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 } });
|
|
1509
1771
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: MessageInputComponent, decorators: [{
|
|
1510
1772
|
type: Component,
|
|
1511
1773
|
args: [{
|
|
@@ -1527,6 +1789,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImpor
|
|
|
1527
1789
|
type: Input
|
|
1528
1790
|
}], commandAutocompleteItemTemplate: [{
|
|
1529
1791
|
type: Input
|
|
1792
|
+
}], mode: [{
|
|
1793
|
+
type: Input
|
|
1530
1794
|
}], acceptedFileTypes: [{
|
|
1531
1795
|
type: Input
|
|
1532
1796
|
}], isMultipleFileUploadEnabled: [{
|
|
@@ -1585,7 +1849,7 @@ class ModalComponent {
|
|
|
1585
1849
|
}
|
|
1586
1850
|
}
|
|
1587
1851
|
ModalComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: ModalComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1588
|
-
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"] }] });
|
|
1589
1853
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: ModalComponent, decorators: [{
|
|
1590
1854
|
type: Component,
|
|
1591
1855
|
args: [{
|
|
@@ -1628,7 +1892,7 @@ class NotificationListComponent {
|
|
|
1628
1892
|
}
|
|
1629
1893
|
}
|
|
1630
1894
|
NotificationListComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: NotificationListComponent, deps: [{ token: NotificationService }], target: i0.ɵɵFactoryTarget.Component });
|
|
1631
|
-
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":
|
|
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 } });
|
|
1632
1896
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: NotificationListComponent, decorators: [{
|
|
1633
1897
|
type: Component,
|
|
1634
1898
|
args: [{
|
|
@@ -1679,7 +1943,10 @@ class MessageActionsBoxComponent {
|
|
|
1679
1943
|
}
|
|
1680
1944
|
}
|
|
1681
1945
|
get isQuoteVisible() {
|
|
1682
|
-
|
|
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));
|
|
1683
1950
|
}
|
|
1684
1951
|
get isEditVisible() {
|
|
1685
1952
|
return (((this.enabledActions.indexOf('edit') !== -1 ||
|
|
@@ -1724,7 +1991,7 @@ class MessageActionsBoxComponent {
|
|
|
1724
1991
|
alert('Feature not yet implemented');
|
|
1725
1992
|
}
|
|
1726
1993
|
quoteClicked() {
|
|
1727
|
-
|
|
1994
|
+
this.channelService.selectMessageToQuote(this.message);
|
|
1728
1995
|
}
|
|
1729
1996
|
editClicked() {
|
|
1730
1997
|
this.isEditing.emit(true);
|
|
@@ -1746,7 +2013,7 @@ class MessageActionsBoxComponent {
|
|
|
1746
2013
|
}
|
|
1747
2014
|
}
|
|
1748
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 });
|
|
1749
|
-
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", "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:
|
|
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 } });
|
|
1750
2017
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: MessageActionsBoxComponent, decorators: [{
|
|
1751
2018
|
type: Component,
|
|
1752
2019
|
args: [{
|
|
@@ -1779,10 +2046,11 @@ class ChannelComponent {
|
|
|
1779
2046
|
this.subscriptions = [];
|
|
1780
2047
|
this.isError$ = this.channelService.channels$.pipe(map(() => false), catchError(() => of(true)), startWith(false));
|
|
1781
2048
|
this.isInitializing$ = this.channelService.channels$.pipe(map((channels) => !channels), catchError(() => of(false)));
|
|
2049
|
+
this.isActiveThread$ = this.channelService.activeParentMessageId$.pipe(map((id) => !!id));
|
|
1782
2050
|
}
|
|
1783
2051
|
}
|
|
1784
2052
|
ChannelComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: ChannelComponent, deps: [{ token: ChannelService }], target: i0.ɵɵFactoryTarget.Component });
|
|
1785
|
-
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: i6.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }], pipes: { "async": i6.AsyncPipe } });
|
|
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 } });
|
|
1786
2054
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: ChannelComponent, decorators: [{
|
|
1787
2055
|
type: Component,
|
|
1788
2056
|
args: [{
|
|
@@ -1882,7 +2150,7 @@ class ChannelHeaderComponent {
|
|
|
1882
2150
|
}
|
|
1883
2151
|
}
|
|
1884
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 });
|
|
1885
|
-
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 } });
|
|
1886
2154
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: ChannelHeaderComponent, decorators: [{
|
|
1887
2155
|
type: Component,
|
|
1888
2156
|
args: [{
|
|
@@ -1967,7 +2235,7 @@ class ChannelPreviewComponent {
|
|
|
1967
2235
|
}
|
|
1968
2236
|
}
|
|
1969
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 });
|
|
1970
|
-
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 } });
|
|
1971
2239
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: ChannelPreviewComponent, decorators: [{
|
|
1972
2240
|
type: Component,
|
|
1973
2241
|
args: [{
|
|
@@ -2008,7 +2276,7 @@ class ChannelListComponent {
|
|
|
2008
2276
|
}
|
|
2009
2277
|
}
|
|
2010
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 });
|
|
2011
|
-
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":
|
|
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 } });
|
|
2012
2280
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: ChannelListComponent, decorators: [{
|
|
2013
2281
|
type: Component,
|
|
2014
2282
|
args: [{
|
|
@@ -2159,7 +2427,7 @@ class MessageReactionsComponent {
|
|
|
2159
2427
|
}
|
|
2160
2428
|
}
|
|
2161
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 });
|
|
2162
|
-
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"] }] });
|
|
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 emoji-mart-emoji\"\n *ngFor=\"\n let reactionType of reactionOptions;\n trackBy: trackByMessageReaction\n \"\n data-testclass=\"emoji-option\"\n (click)=\"react(reactionType)\"\n (keyup.enter)=\"react(reactionType)\"\n >\n <div\n *ngIf=\"getLatestUserByReaction(reactionType) as user\"\n class=\"latest-user\"\n (click)=\"hideTooltip()\"\n (keyup.enter)=\"hideTooltip()\"\n (mouseenter)=\"showTooltip($event, reactionType)\"\n (mouseleave)=\"hideTooltip()\"\n attr.data-testid=\"{{ reactionType }}-last-user\"\n >\n <stream-avatar\n attr.data-testid=\"{{ reactionType }}-avatar\"\n [imageUrl]=\"user.image\"\n [name]=\"user.name || user.id\"\n [size]=\"20\"\n ></stream-avatar>\n </div>\n <span class=\"emoji\" style=\"width: 20px; height: 20px; top: 10px\">\n {{ getEmojiByReaction(reactionType) }}\n </span>\n <span\n *ngIf=\"\n messageReactionCounts[reactionType] &&\n messageReactionCounts[reactionType]! > 0\n \"\n class=\"str-chat__message-reactions-list-item__count\"\n attr.data-testid=\"{{ reactionType }}-reaction-count\"\n >\n {{ messageReactionCounts[reactionType] }}\n </span>\n </li>\n </ul>\n</div>\n", styles: [".emoji {position: relative; display: inline-block; }"], components: [{ type: AvatarComponent, selector: "stream-avatar", inputs: ["name", "imageUrl", "size"] }], directives: [{ type: i6.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i6.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i6.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }] });
|
|
2163
2431
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: MessageReactionsComponent, decorators: [{
|
|
2164
2432
|
type: Component,
|
|
2165
2433
|
args: [{
|
|
@@ -2187,95 +2455,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImpor
|
|
|
2187
2455
|
args: ['selectorTooltip']
|
|
2188
2456
|
}] } });
|
|
2189
2457
|
|
|
2190
|
-
class ImageLoadService {
|
|
2191
|
-
constructor() {
|
|
2192
|
-
this.imageLoad$ = new Subject();
|
|
2193
|
-
}
|
|
2194
|
-
}
|
|
2195
|
-
ImageLoadService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: ImageLoadService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
2196
|
-
ImageLoadService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: ImageLoadService, providedIn: 'root' });
|
|
2197
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: ImageLoadService, decorators: [{
|
|
2198
|
-
type: Injectable,
|
|
2199
|
-
args: [{
|
|
2200
|
-
providedIn: 'root',
|
|
2201
|
-
}]
|
|
2202
|
-
}], ctorParameters: function () { return []; } });
|
|
2203
|
-
|
|
2204
|
-
class AttachmentListComponent {
|
|
2205
|
-
constructor(imageLoadService, channelService) {
|
|
2206
|
-
this.imageLoadService = imageLoadService;
|
|
2207
|
-
this.channelService = channelService;
|
|
2208
|
-
this.attachments = [];
|
|
2209
|
-
this.orderedAttachments = [];
|
|
2210
|
-
}
|
|
2211
|
-
ngOnChanges() {
|
|
2212
|
-
this.orderedAttachments = [
|
|
2213
|
-
...this.attachments.filter((a) => this.isImage(a)),
|
|
2214
|
-
...this.attachments.filter((a) => this.isFile(a)),
|
|
2215
|
-
...this.attachments.filter((a) => this.isCard(a)),
|
|
2216
|
-
];
|
|
2217
|
-
}
|
|
2218
|
-
trackById(index) {
|
|
2219
|
-
return index;
|
|
2220
|
-
}
|
|
2221
|
-
isImage(attachment) {
|
|
2222
|
-
return isImageAttachment(attachment);
|
|
2223
|
-
}
|
|
2224
|
-
isFile(attachment) {
|
|
2225
|
-
return attachment.type === 'file';
|
|
2226
|
-
}
|
|
2227
|
-
isCard(attachment) {
|
|
2228
|
-
return (!attachment.type ||
|
|
2229
|
-
(attachment.type === 'image' && !this.isImage(attachment)) ||
|
|
2230
|
-
attachment.type === 'giphy');
|
|
2231
|
-
}
|
|
2232
|
-
imageLoaded() {
|
|
2233
|
-
this.imageLoadService.imageLoad$.next();
|
|
2234
|
-
}
|
|
2235
|
-
hasFileSize(attachment) {
|
|
2236
|
-
return (attachment.file_size && Number.isFinite(Number(attachment.file_size)));
|
|
2237
|
-
}
|
|
2238
|
-
getFileSize(attachment) {
|
|
2239
|
-
return prettybytes(attachment.file_size);
|
|
2240
|
-
}
|
|
2241
|
-
trimUrl(url) {
|
|
2242
|
-
if (url !== undefined && url !== null) {
|
|
2243
|
-
const [trimmedUrl] = url
|
|
2244
|
-
.replace(/^(?:https?:\/\/)?(?:www\.)?/i, '')
|
|
2245
|
-
.split('/');
|
|
2246
|
-
return trimmedUrl;
|
|
2247
|
-
}
|
|
2248
|
-
return null;
|
|
2249
|
-
}
|
|
2250
|
-
sendAction(action) {
|
|
2251
|
-
void this.channelService.sendAction(this.messageId, {
|
|
2252
|
-
[action.name]: action.value,
|
|
2253
|
-
});
|
|
2254
|
-
}
|
|
2255
|
-
trackByActionValue(_, item) {
|
|
2256
|
-
return item.value;
|
|
2257
|
-
}
|
|
2258
|
-
}
|
|
2259
|
-
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 });
|
|
2260
|
-
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"] }] });
|
|
2261
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: AttachmentListComponent, decorators: [{
|
|
2262
|
-
type: Component,
|
|
2263
|
-
args: [{
|
|
2264
|
-
selector: 'stream-attachment-list',
|
|
2265
|
-
templateUrl: './attachment-list.component.html',
|
|
2266
|
-
styles: [],
|
|
2267
|
-
}]
|
|
2268
|
-
}], ctorParameters: function () { return [{ type: ImageLoadService }, { type: ChannelService }]; }, propDecorators: { messageId: [{
|
|
2269
|
-
type: Input
|
|
2270
|
-
}], attachments: [{
|
|
2271
|
-
type: Input
|
|
2272
|
-
}] } });
|
|
2273
|
-
|
|
2274
2458
|
class MessageComponent {
|
|
2275
2459
|
constructor(chatClientService, channelService) {
|
|
2276
2460
|
this.chatClientService = chatClientService;
|
|
2277
2461
|
this.channelService = channelService;
|
|
2278
2462
|
this.enabledMessageActions = [];
|
|
2463
|
+
this.mode = 'main';
|
|
2279
2464
|
this.isActionBoxOpen = false;
|
|
2280
2465
|
this.isReactionSelectorOpen = false;
|
|
2281
2466
|
this.isPressedOnMobile = false;
|
|
@@ -2284,46 +2469,8 @@ class MessageComponent {
|
|
|
2284
2469
|
this.user = this.chatClientService.chatClient.user;
|
|
2285
2470
|
}
|
|
2286
2471
|
ngOnChanges(changes) {
|
|
2287
|
-
var _a, _b;
|
|
2288
2472
|
if (changes.message) {
|
|
2289
|
-
|
|
2290
|
-
if (!content) {
|
|
2291
|
-
this.messageTextParts = [];
|
|
2292
|
-
}
|
|
2293
|
-
else {
|
|
2294
|
-
// Backend will wrap HTML content with <p></p>\n
|
|
2295
|
-
if (content.startsWith('<p>')) {
|
|
2296
|
-
content = content.replace('<p>', '');
|
|
2297
|
-
}
|
|
2298
|
-
if (content.endsWith('</p>\n')) {
|
|
2299
|
-
content = content.replace('</p>\n', '');
|
|
2300
|
-
}
|
|
2301
|
-
if (!this.message.mentioned_users ||
|
|
2302
|
-
this.message.mentioned_users.length === 0) {
|
|
2303
|
-
this.messageTextParts = [{ content, type: 'text' }];
|
|
2304
|
-
}
|
|
2305
|
-
else {
|
|
2306
|
-
this.messageTextParts = [];
|
|
2307
|
-
let text = content;
|
|
2308
|
-
this.message.mentioned_users.forEach((user) => {
|
|
2309
|
-
const mention = `@${user.name || user.id}`;
|
|
2310
|
-
const precedingText = text.substring(0, text.indexOf(mention));
|
|
2311
|
-
this.messageTextParts.push({
|
|
2312
|
-
content: precedingText,
|
|
2313
|
-
type: 'text',
|
|
2314
|
-
});
|
|
2315
|
-
this.messageTextParts.push({
|
|
2316
|
-
content: mention,
|
|
2317
|
-
type: 'mention',
|
|
2318
|
-
user,
|
|
2319
|
-
});
|
|
2320
|
-
text = text.replace(precedingText + mention, '');
|
|
2321
|
-
});
|
|
2322
|
-
if (text) {
|
|
2323
|
-
this.messageTextParts.push({ content: text, type: 'text' });
|
|
2324
|
-
}
|
|
2325
|
-
}
|
|
2326
|
-
}
|
|
2473
|
+
this.createMessageParts();
|
|
2327
2474
|
}
|
|
2328
2475
|
}
|
|
2329
2476
|
get isSentByCurrentUser() {
|
|
@@ -2365,7 +2512,8 @@ class MessageComponent {
|
|
|
2365
2512
|
this.message.type === 'system' ||
|
|
2366
2513
|
this.message.type === 'ephemeral' ||
|
|
2367
2514
|
this.message.status === 'failed' ||
|
|
2368
|
-
this.message.status === 'sending'
|
|
2515
|
+
this.message.status === 'sending' ||
|
|
2516
|
+
(this.mode === 'thread' && !this.message.parent_id));
|
|
2369
2517
|
}
|
|
2370
2518
|
get hasAttachment() {
|
|
2371
2519
|
var _a;
|
|
@@ -2376,6 +2524,21 @@ class MessageComponent {
|
|
|
2376
2524
|
return (!!((_a = this.message) === null || _a === void 0 ? void 0 : _a.reaction_counts) &&
|
|
2377
2525
|
Object.keys(this.message.reaction_counts).length > 0);
|
|
2378
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
|
+
}
|
|
2379
2542
|
resendMessage() {
|
|
2380
2543
|
void this.channelService.resendMessage(this.message);
|
|
2381
2544
|
}
|
|
@@ -2397,9 +2560,53 @@ class MessageComponent {
|
|
|
2397
2560
|
};
|
|
2398
2561
|
window.addEventListener('click', eventHandler);
|
|
2399
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
|
+
}
|
|
2400
2607
|
}
|
|
2401
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 });
|
|
2402
|
-
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 !== 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 isMessageDeliveredAndRead &&\n canReceiveReadEvents !== false &&\n enabledMessageActions.indexOf('read-events') !== -1;\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 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\"\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 <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: ["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: 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 (mouseleave)=\"isActionBoxOpen = false\"\n>\n <ng-container *ngIf=\"!message?.deleted_at; else deletedMessage\">\n <ng-container *ngIf=\"message?.type !== 'system'; else systemMessage\">\n <ng-container\n *ngIf=\"\n isSentByCurrentUser &&\n ((isLastSentMessage && message?.status === 'received') ||\n message?.status === 'sending')\n \"\n >\n <ng-container *ngIf=\"message?.status === 'sending'; else sentStatus\">\n <ng-container *ngTemplateOutlet=\"sendingStatus\"></ng-container>\n </ng-container>\n <ng-template #sentStatus>\n <ng-container\n *ngIf=\"\n mode === 'main' &&\n isMessageDeliveredAndRead &&\n canDisplayReadStatus;\n else deliveredStatus\n \"\n >\n <ng-container *ngTemplateOutlet=\"readStatus\"></ng-container>\n </ng-container>\n </ng-template>\n </ng-container>\n <stream-avatar\n data-testid=\"avatar\"\n class=\"str-chat-angular__avatar-host\"\n [imageUrl]=\"message?.user?.image\"\n [name]=\"message?.user?.name || message?.user?.id\"\n ></stream-avatar>\n <div class=\"str-chat__message-inner\">\n <div\n class=\"str-chat__message-simple__actions\"\n data-testid=\"message-options\"\n *ngIf=\"areOptionsVisible\"\n >\n <div\n data-testid=\"message-actions-container\"\n class=\"\n str-chat__message-simple__actions__action\n str-chat__message-simple__actions__action--options\n \"\n [class.str-chat-angular__message-simple__actions__action--options--editing]=\"\n isEditing\n \"\n >\n <stream-message-actions-box\n [isOpen]=\"isActionBoxOpen\"\n [isMine]=\"isSentByCurrentUser\"\n [enabledActions]=\"enabledMessageActions\"\n [message]=\"message\"\n (displayedActionsCount)=\"visibleMessageActionsCount = $event\"\n (isEditing)=\"isEditing = $event; isActionBoxOpen = !isEditing\"\n [messageInputTemplate]=\"messageInputTemplate\"\n ></stream-message-actions-box>\n <stream-icon\n *ngIf=\"visibleMessageActionsCount > 0\"\n data-testid=\"action-icon\"\n icon=\"action-icon\"\n (keyup.enter)=\"isActionBoxOpen = !isActionBoxOpen\"\n (click)=\"isActionBoxOpen = !isActionBoxOpen\"\n ></stream-icon>\n </div>\n <!-- eslint-disable @angular-eslint/template/conditional-complexity -->\n <div\n *ngIf=\"\n enabledMessageActions.indexOf('send-reply') !== -1 &&\n mode === 'main'\n \"\n class=\"\n str-chat__message-simple__actions__action\n str-chat__message-simple__actions__action--thread\n \"\n data-testid=\"reply-in-thread\"\n (click)=\"setAsActiveParentMessage()\"\n (keyup.enter)=\"setAsActiveParentMessage()\"\n >\n <stream-icon icon=\"reply-in-thread\"></stream-icon>\n </div>\n <div\n *ngIf=\"\n areReactionsEnabled !== false &&\n canReactToMessage !== false &&\n enabledMessageActions.indexOf('send-reaction') !== -1\n \"\n class=\"\n str-chat__message-simple__actions__action\n str-chat__message-simple__actions__action--reactions\n \"\n data-testid=\"reaction-icon\"\n (click)=\"isReactionSelectorOpen = !isReactionSelectorOpen\"\n (keyup.enter)=\"isReactionSelectorOpen = !isReactionSelectorOpen\"\n >\n <stream-icon icon=\"reaction-icon\"></stream-icon>\n </div>\n </div>\n <!-- eslint-enable @angular-eslint/template/conditional-complexity -->\n <stream-message-reactions\n *ngIf=\"areReactionsEnabled !== false\"\n [messageReactionCounts]=\"message?.reaction_counts || {}\"\n [latestReactions]=\"message?.latest_reactions || []\"\n [(isSelectorOpen)]=\"isReactionSelectorOpen\"\n [messageId]=\"message?.id\"\n [ownReactions]=\"message?.own_reactions || []\"\n ></stream-message-reactions>\n <stream-attachment-list\n *ngIf=\"hasAttachment && !message?.quoted_message\"\n [attachments]=\"message!.attachments!\"\n [messageId]=\"message!.id\"\n ></stream-attachment-list>\n <div class=\"str-chat__message-text\" *ngIf=\"message?.text\">\n <div\n data-testid=\"inner-message\"\n class=\"\n str-chat__message-text-inner str-chat__message-simple-text-inner\n \"\n [class.str-chat__message-light-text-inner--has-attachment]=\"\n hasAttachment\n \"\n (click)=\"\n message?.status === 'failed' && message?.errorStatusCode !== 403\n ? resendMessage()\n : undefined\n \"\n (keyup.enter)=\"\n message?.status === 'failed' && message?.errorStatusCode !== 403\n ? resendMessage()\n : undefined\n \"\n >\n <ng-container *ngTemplateOutlet=\"quotedMessage\"></ng-container>\n <stream-attachment-list\n *ngIf=\"hasAttachment && message?.quoted_message\"\n [attachments]=\"message!.attachments!\"\n [messageId]=\"message!.id\"\n ></stream-attachment-list>\n <div\n data-testid=\"client-error-message\"\n *ngIf=\"message?.type === 'error'\"\n class=\"str-chat__simple-message--error-message\"\n >\n {{ \"streamChat.Error \u00B7 Unsent\" | translate }}\n </div>\n <div\n data-testid=\"error-message\"\n *ngIf=\"message?.status === 'failed'\"\n class=\"str-chat__simple-message--error-message\"\n >\n {{\n (message?.errorStatusCode === 403\n ? \"streamChat.Message Failed \u00B7 Unauthorized\"\n : \"streamChat.Message Failed \u00B7 Click to try again\"\n ) | translate\n }}\n </div>\n <div\n (click)=\"textClicked()\"\n (keyup.enter)=\"textClicked()\"\n data-testid=\"text\"\n >\n <p>\n <!-- eslint-disable-next-line @angular-eslint/template/use-track-by-function -->\n <ng-container *ngFor=\"let part of messageTextParts\">\n <span\n *ngIf=\"part.type === 'text'; else mention\"\n [innerHTML]=\"part.content\"\n ></span>\n <ng-template #mention>\n <ng-container *ngIf=\"mentionTemplate; else defaultMention\">\n <ng-container\n *ngTemplateOutlet=\"\n mentionTemplate;\n context: { user: part.user! }\n \"\n ></ng-container>\n </ng-container>\n <ng-template #defaultMention>\n <b>{{ part.content }}</b>\n </ng-template>\n </ng-template>\n </ng-container>\n </p>\n </div>\n </div>\n </div>\n <div class=\"str-chat__message-simple-reply-button\">\n <button\n *ngIf=\"\n !!message?.reply_count &&\n mode !== 'thread' &&\n enabledMessageActions.indexOf('send-reply') !== -1\n \"\n class=\"str-chat__message-replies-count-button\"\n data-testid=\"reply-count-button\"\n (click)=\"setAsActiveParentMessage()\"\n >\n <stream-icon icon=\"reply\"></stream-icon>\n {{message?.reply_count === 1 ? ('streamChat.1 reply' | translate) : ('streamChat.{{ replyCount }}\n replies' | translate:replyCountParam)}}\n </button>\n </div>\n <div class=\"str-chat__message-data str-chat__message-simple-data\">\n <span\n data-testid=\"sender\"\n *ngIf=\"!isSentByCurrentUser\"\n class=\"str-chat__message-simple-name\"\n >\n {{ message?.user?.name ? message?.user?.name : message?.user?.id }}\n </span>\n <span data-testid=\"date\" class=\"str-chat__message-simple-timestamp\">\n {{ parsedDate }}\n </span>\n </div>\n </div>\n </ng-container>\n </ng-container>\n</div>\n\n<ng-template #sendingStatus>\n <span\n class=\"\n str-chat__message-simple-status str-chat__message-simple-status-angular\n \"\n data-testid=\"sending-indicator\"\n >\n <div class=\"str-chat__tooltip\">\n {{ \"streamChat.Sending...\" | translate }}\n </div>\n <stream-loading-indicator\n data-testid=\"loading-indicator\"\n ></stream-loading-indicator>\n </span>\n</ng-template>\n<ng-template #readStatus>\n <span\n class=\"\n str-chat__message-simple-status str-chat__message-simple-status-angular\n \"\n data-testid=\"read-indicator\"\n >\n <div class=\"str-chat__tooltip\" data-testid=\"read-by-tooltip\">\n {{ readByText }}\n </div>\n <stream-avatar\n class=\"str-chat-angular__avatar-host\"\n data-test-id=\"last-read-user-avatar\"\n [size]=\"15\"\n [imageUrl]=\"lastReadUser?.image\"\n [name]=\"lastReadUser?.name || lastReadUser?.id\"\n ></stream-avatar>\n <span\n data-test-id=\"read-by-length\"\n *ngIf=\"isReadByMultipleUsers\"\n class=\"str-chat__message-simple-status-number\"\n >\n {{ (message?.readBy)!.length }}\n </span>\n </span>\n</ng-template>\n<ng-template #deliveredStatus>\n <span\n *ngIf=\"mode === 'main'\"\n class=\"\n str-chat__message-simple-status str-chat__message-simple-status-angular\n \"\n data-testid=\"delivered-indicator\"\n >\n <div class=\"str-chat__tooltip\">\n {{ \"streamChat.Delivered\" | translate }}\n </div>\n <stream-icon\n data-testid=\"delivered-icon\"\n icon=\"delivered-icon\"\n ></stream-icon>\n </span>\n</ng-template>\n\n<ng-template #deletedMessage>\n <div data-testid=\"message-deleted-component\">\n <div class=\"str-chat__message--deleted-inner\" translate>\n streamChat.This message was deleted...\n </div>\n </div>\n</ng-template>\n\n<ng-template #systemMessage>\n <div data-testid=\"system-message\" class=\"str-chat__message--system\">\n <div class=\"str-chat__message--system__text\">\n <div class=\"str-chat__message--system__line\"></div>\n <p>{{ message?.text }}</p>\n <div class=\"str-chat__message--system__line\"></div>\n </div>\n <div class=\"str-chat__message--system__date\">\n {{ parsedDate }}\n </div>\n </div>\n</ng-template>\n\n<ng-template #quotedMessage>\n <div\n *ngIf=\"message?.quoted_message\"\n class=\"quoted-message\"\n data-testid=\"quoted-message-container\"\n [class.mine]=\"isSentByCurrentUser\"\n >\n <stream-avatar\n data-testid=\"qouted-message-avatar\"\n class=\"str-chat-angular__avatar-host\"\n [imageUrl]=\"message?.quoted_message?.user?.image\"\n [name]=\"\n message?.quoted_message?.user?.name || message?.quoted_message?.user?.id\n \"\n [size]=\"20\"\n ></stream-avatar>\n <div class=\"quoted-message-inner\">\n <stream-attachment-list\n *ngIf=\"\n message?.quoted_message?.attachments &&\n message?.quoted_message?.attachments?.length\n \"\n [attachments]=\"quotedMessageAttachments\"\n [messageId]=\"message?.quoted_message?.id\"\n ></stream-attachment-list>\n <div\n data-testid=\"quoted-message-text\"\n [innerHTML]=\"\n message?.quoted_message?.html || message?.quoted_message?.text\n \"\n ></div>\n </div>\n </div>\n</ng-template>\n", components: [{ type: AvatarComponent, selector: "stream-avatar", inputs: ["name", "imageUrl", "size"] }, { type: MessageActionsBoxComponent, selector: "stream-message-actions-box", inputs: ["messageInputTemplate", "isOpen", "isMine", "message", "enabledActions"], outputs: ["displayedActionsCount", "isEditing"] }, { type: IconComponent, selector: "stream-icon", inputs: ["icon", "size"] }, { type: MessageReactionsComponent, selector: "stream-message-reactions", inputs: ["messageId", "messageReactionCounts", "isSelectorOpen", "latestReactions", "ownReactions"], outputs: ["isSelectorOpenChange"] }, { type: AttachmentListComponent, selector: "stream-attachment-list", inputs: ["messageId", "attachments"] }, { type: LoadingIndicatorComponent, selector: "stream-loading-indicator", inputs: ["size", "color"] }], directives: [{ type: i6.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i6.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet"] }, { type: i6.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i1.TranslateDirective, selector: "[translate],[ngx-translate]", inputs: ["translate", "translateParams"] }], pipes: { "translate": i1.TranslatePipe } });
|
|
2403
2610
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: MessageComponent, decorators: [{
|
|
2404
2611
|
type: Component,
|
|
2405
2612
|
args: [{
|
|
@@ -2423,6 +2630,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImpor
|
|
|
2423
2630
|
type: Input
|
|
2424
2631
|
}], canReceiveReadEvents: [{
|
|
2425
2632
|
type: Input
|
|
2633
|
+
}], mode: [{
|
|
2634
|
+
type: Input
|
|
2426
2635
|
}], container: [{
|
|
2427
2636
|
type: ViewChild,
|
|
2428
2637
|
args: ['container']
|
|
@@ -2446,7 +2655,7 @@ class TextareaComponent {
|
|
|
2446
2655
|
}
|
|
2447
2656
|
}
|
|
2448
2657
|
TextareaComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: TextareaComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2449
|
-
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 } });
|
|
2450
2659
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: TextareaComponent, decorators: [{
|
|
2451
2660
|
type: Component,
|
|
2452
2661
|
args: [{
|
|
@@ -2631,7 +2840,7 @@ class AutocompleteTextareaComponent {
|
|
|
2631
2840
|
}
|
|
2632
2841
|
}
|
|
2633
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 });
|
|
2634
|
-
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":
|
|
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 } });
|
|
2635
2844
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: AutocompleteTextareaComponent, decorators: [{
|
|
2636
2845
|
type: Component,
|
|
2637
2846
|
args: [{
|
|
@@ -2716,22 +2925,17 @@ class MessageListComponent {
|
|
|
2716
2925
|
*/
|
|
2717
2926
|
/* eslint-disable-next-line @angular-eslint/no-input-rename */
|
|
2718
2927
|
this.enabledMessageActionsInput = undefined;
|
|
2928
|
+
this.mode = 'main';
|
|
2719
2929
|
this.enabledMessageActions = [];
|
|
2720
2930
|
this.class = 'str-chat-angular__main-panel-inner str-chat-angular__message-list-host';
|
|
2721
2931
|
this.unreadMessageCount = 0;
|
|
2722
2932
|
this.groupStyles = [];
|
|
2723
2933
|
this.authorizedMessageActions = ['flag'];
|
|
2724
2934
|
this.isUserScrolledUpThreshold = 300;
|
|
2725
|
-
this.
|
|
2935
|
+
this.subscriptions = [];
|
|
2936
|
+
this.subscriptions.push(this.channelService.activeChannel$.subscribe((channel) => {
|
|
2726
2937
|
var _a;
|
|
2727
|
-
this.
|
|
2728
|
-
this.hasNewMessages = true;
|
|
2729
|
-
this.isUserScrolledUp = false;
|
|
2730
|
-
this.containerHeight = undefined;
|
|
2731
|
-
this.olderMassagesLoaded = false;
|
|
2732
|
-
this.oldestMessageDate = undefined;
|
|
2733
|
-
this.unreadMessageCount = 0;
|
|
2734
|
-
this.isNewMessageSentByUser = undefined;
|
|
2938
|
+
this.resetScrollState();
|
|
2735
2939
|
const capabilites = (_a = channel === null || channel === void 0 ? void 0 : channel.data) === null || _a === void 0 ? void 0 : _a.own_capabilities;
|
|
2736
2940
|
if (capabilites) {
|
|
2737
2941
|
this.canReactToMessage = capabilites.indexOf('send-reaction') !== -1;
|
|
@@ -2760,47 +2964,16 @@ class MessageListComponent {
|
|
|
2760
2964
|
this.authorizedMessageActions.push('delete');
|
|
2761
2965
|
this.authorizedMessageActions.push('delete-any');
|
|
2762
2966
|
}
|
|
2763
|
-
|
|
2764
|
-
|
|
2765
|
-
});
|
|
2766
|
-
this.messages$ = this.channelService.activeChannelMessages$.pipe(tap((messages) => {
|
|
2767
|
-
var _a, _b, _c, _d, _e;
|
|
2768
|
-
if (messages.length === 0) {
|
|
2769
|
-
return;
|
|
2770
|
-
}
|
|
2771
|
-
const currentLatestMessageDate = messages[messages.length - 1].created_at;
|
|
2772
|
-
if (!this.latestMessageDate ||
|
|
2773
|
-
((_a = this.latestMessageDate) === null || _a === void 0 ? void 0 : _a.getTime()) < currentLatestMessageDate.getTime()) {
|
|
2774
|
-
this.latestMessageDate = currentLatestMessageDate;
|
|
2775
|
-
this.hasNewMessages = true;
|
|
2776
|
-
this.isNewMessageSentByUser =
|
|
2777
|
-
((_b = messages[messages.length - 1].user) === null || _b === void 0 ? void 0 : _b.id) ===
|
|
2778
|
-
((_d = (_c = this.chatClientService.chatClient) === null || _c === void 0 ? void 0 : _c.user) === null || _d === void 0 ? void 0 : _d.id);
|
|
2779
|
-
if (this.isUserScrolledUp) {
|
|
2780
|
-
this.unreadMessageCount++;
|
|
2967
|
+
if (capabilites.indexOf('send-reply') !== -1) {
|
|
2968
|
+
this.authorizedMessageActions.push('send-reply');
|
|
2781
2969
|
}
|
|
2970
|
+
if (capabilites.indexOf('quote-message') !== -1) {
|
|
2971
|
+
this.authorizedMessageActions.push('quote-message');
|
|
2972
|
+
}
|
|
2973
|
+
this.setEnabledActions();
|
|
2782
2974
|
}
|
|
2783
|
-
const currentOldestMessageDate = messages[0].created_at;
|
|
2784
|
-
if (!this.oldestMessageDate) {
|
|
2785
|
-
this.oldestMessageDate = currentOldestMessageDate;
|
|
2786
|
-
}
|
|
2787
|
-
else if (((_e = this.oldestMessageDate) === null || _e === void 0 ? void 0 : _e.getTime()) > currentOldestMessageDate.getTime()) {
|
|
2788
|
-
this.oldestMessageDate = currentOldestMessageDate;
|
|
2789
|
-
this.olderMassagesLoaded = true;
|
|
2790
|
-
}
|
|
2791
|
-
}), tap((messages) => {
|
|
2792
|
-
this.groupStyles = messages.map((m, i) => getGroupStyles(m, messages[i - 1], messages[i + 1]));
|
|
2793
|
-
}), tap((messages) => {
|
|
2794
|
-
var _a;
|
|
2795
|
-
return (this.lastSentMessageId = (_a = [...messages]
|
|
2796
|
-
.reverse()
|
|
2797
|
-
.find((m) => {
|
|
2798
|
-
var _a, _b, _c;
|
|
2799
|
-
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) &&
|
|
2800
|
-
m.status !== 'sending';
|
|
2801
|
-
})) === null || _a === void 0 ? void 0 : _a.id);
|
|
2802
2975
|
}));
|
|
2803
|
-
this.imageLoadService.imageLoad$.subscribe(() => {
|
|
2976
|
+
this.subscriptions.push(this.imageLoadService.imageLoad$.subscribe(() => {
|
|
2804
2977
|
if (!this.isUserScrolledUp) {
|
|
2805
2978
|
this.scrollToBottom();
|
|
2806
2979
|
// Hacky and unreliable workaround to scroll down after loaded images move the scrollbar
|
|
@@ -2808,12 +2981,27 @@ class MessageListComponent {
|
|
|
2808
2981
|
this.scrollToBottom();
|
|
2809
2982
|
}, 300);
|
|
2810
2983
|
}
|
|
2811
|
-
});
|
|
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$();
|
|
2812
2997
|
}
|
|
2813
2998
|
ngOnChanges(changes) {
|
|
2814
2999
|
if (changes.enabledMessageActionsInput) {
|
|
2815
3000
|
this.setEnabledActions();
|
|
2816
3001
|
}
|
|
3002
|
+
if (changes.mode) {
|
|
3003
|
+
this.setMessages$();
|
|
3004
|
+
}
|
|
2817
3005
|
}
|
|
2818
3006
|
ngAfterViewChecked() {
|
|
2819
3007
|
if (this.hasNewMessages) {
|
|
@@ -2839,6 +3027,9 @@ class MessageListComponent {
|
|
|
2839
3027
|
this.containerHeight = this.scrollContainer.nativeElement.scrollHeight;
|
|
2840
3028
|
}
|
|
2841
3029
|
}
|
|
3030
|
+
ngOnDestroy() {
|
|
3031
|
+
this.subscriptions.forEach((s) => s.unsubscribe());
|
|
3032
|
+
}
|
|
2842
3033
|
trackByMessageId(index, item) {
|
|
2843
3034
|
return item.id;
|
|
2844
3035
|
}
|
|
@@ -2847,6 +3038,7 @@ class MessageListComponent {
|
|
|
2847
3038
|
this.scrollContainer.nativeElement.scrollHeight;
|
|
2848
3039
|
}
|
|
2849
3040
|
scrolled() {
|
|
3041
|
+
var _a, _b;
|
|
2850
3042
|
this.isUserScrolledUp =
|
|
2851
3043
|
this.scrollContainer.nativeElement.scrollHeight -
|
|
2852
3044
|
(this.scrollContainer.nativeElement.scrollTop +
|
|
@@ -2855,14 +3047,22 @@ class MessageListComponent {
|
|
|
2855
3047
|
if (!this.isUserScrolledUp) {
|
|
2856
3048
|
this.unreadMessageCount = 0;
|
|
2857
3049
|
}
|
|
2858
|
-
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))) {
|
|
2859
3055
|
this.containerHeight = this.scrollContainer.nativeElement.scrollHeight;
|
|
2860
|
-
|
|
3056
|
+
this.mode === 'main'
|
|
3057
|
+
? void this.channelService.loadMoreMessages()
|
|
3058
|
+
: void this.channelService.loadMoreThreadReplies();
|
|
2861
3059
|
}
|
|
3060
|
+
this.prevScrollTop = this.scrollContainer.nativeElement.scrollTop;
|
|
2862
3061
|
}
|
|
2863
3062
|
preserveScrollbarPosition() {
|
|
2864
3063
|
this.scrollContainer.nativeElement.scrollTop =
|
|
2865
|
-
this.
|
|
3064
|
+
(this.prevScrollTop || 0) +
|
|
3065
|
+
(this.scrollContainer.nativeElement.scrollHeight - this.containerHeight);
|
|
2866
3066
|
}
|
|
2867
3067
|
setEnabledActions() {
|
|
2868
3068
|
this.enabledMessageActions = [];
|
|
@@ -2874,6 +3074,8 @@ class MessageListComponent {
|
|
|
2874
3074
|
...this.enabledMessageActionsInput,
|
|
2875
3075
|
'send-reaction',
|
|
2876
3076
|
'read-events',
|
|
3077
|
+
'send-reply',
|
|
3078
|
+
'quote-message',
|
|
2877
3079
|
];
|
|
2878
3080
|
this.enabledMessageActionsInput.forEach((action) => {
|
|
2879
3081
|
const isAuthorized = this.authorizedMessageActions.indexOf(action) !== -1;
|
|
@@ -2882,9 +3084,61 @@ class MessageListComponent {
|
|
|
2882
3084
|
}
|
|
2883
3085
|
});
|
|
2884
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
|
+
}
|
|
2885
3139
|
}
|
|
2886
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 });
|
|
2887
|
-
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 } });
|
|
2888
3142
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: MessageListComponent, decorators: [{
|
|
2889
3143
|
type: Component,
|
|
2890
3144
|
args: [{
|
|
@@ -2903,12 +3157,49 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImpor
|
|
|
2903
3157
|
}], enabledMessageActionsInput: [{
|
|
2904
3158
|
type: Input,
|
|
2905
3159
|
args: ['enabledMessageActions']
|
|
3160
|
+
}], mode: [{
|
|
3161
|
+
type: Input
|
|
2906
3162
|
}], class: [{
|
|
2907
3163
|
type: HostBinding,
|
|
2908
3164
|
args: ['class']
|
|
2909
3165
|
}], scrollContainer: [{
|
|
2910
3166
|
type: ViewChild,
|
|
2911
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']
|
|
2912
3203
|
}] } });
|
|
2913
3204
|
|
|
2914
3205
|
class StreamAvatarModule {
|
|
@@ -2944,7 +3235,8 @@ StreamChatModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "12.0.0", versio
|
|
|
2944
3235
|
NotificationListComponent,
|
|
2945
3236
|
AttachmentPreviewListComponent,
|
|
2946
3237
|
ModalComponent,
|
|
2947
|
-
TextareaDirective
|
|
3238
|
+
TextareaDirective,
|
|
3239
|
+
ThreadComponent], imports: [CommonModule, TranslateModule, StreamAvatarModule], exports: [ChannelComponent,
|
|
2948
3240
|
ChannelHeaderComponent,
|
|
2949
3241
|
ChannelListComponent,
|
|
2950
3242
|
ChannelPreviewComponent,
|
|
@@ -2960,7 +3252,8 @@ StreamChatModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "12.0.0", versio
|
|
|
2960
3252
|
NotificationListComponent,
|
|
2961
3253
|
AttachmentPreviewListComponent,
|
|
2962
3254
|
ModalComponent,
|
|
2963
|
-
StreamAvatarModule
|
|
3255
|
+
StreamAvatarModule,
|
|
3256
|
+
ThreadComponent] });
|
|
2964
3257
|
StreamChatModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: StreamChatModule, imports: [[CommonModule, TranslateModule, StreamAvatarModule], StreamAvatarModule] });
|
|
2965
3258
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: StreamChatModule, decorators: [{
|
|
2966
3259
|
type: NgModule,
|
|
@@ -2983,6 +3276,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImpor
|
|
|
2983
3276
|
AttachmentPreviewListComponent,
|
|
2984
3277
|
ModalComponent,
|
|
2985
3278
|
TextareaDirective,
|
|
3279
|
+
ThreadComponent,
|
|
2986
3280
|
],
|
|
2987
3281
|
imports: [CommonModule, TranslateModule, StreamAvatarModule],
|
|
2988
3282
|
exports: [
|
|
@@ -3003,6 +3297,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImpor
|
|
|
3003
3297
|
AttachmentPreviewListComponent,
|
|
3004
3298
|
ModalComponent,
|
|
3005
3299
|
StreamAvatarModule,
|
|
3300
|
+
ThreadComponent,
|
|
3006
3301
|
],
|
|
3007
3302
|
}]
|
|
3008
3303
|
}] });
|
|
@@ -3065,5 +3360,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImpor
|
|
|
3065
3360
|
* Generated bundle index. Do not edit.
|
|
3066
3361
|
*/
|
|
3067
3362
|
|
|
3068
|
-
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 };
|
|
3069
3364
|
//# sourceMappingURL=stream-chat-angular.js.map
|