stream-chat-angular 2.10.0 → 2.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/assets/i18n/en.d.ts +2 -0
- package/assets/version.d.ts +1 -1
- package/bundles/stream-chat-angular.umd.js +449 -182
- 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 +158 -40
- package/esm2015/lib/icon/icon.component.js +2 -2
- package/esm2015/lib/message/message.component.js +18 -3
- package/esm2015/lib/message-actions-box/message-actions-box.component.js +1 -1
- package/esm2015/lib/message-input/message-input.component.js +32 -8
- package/esm2015/lib/message-list/message-list.component.js +100 -53
- package/esm2015/lib/message-preview.js +3 -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 +351 -108
- package/fesm2015/stream-chat-angular.js.map +1 -1
- package/lib/channel/channel.component.d.ts +2 -1
- package/lib/channel.service.d.ts +18 -7
- package/lib/icon/icon.component.d.ts +1 -1
- package/lib/message/message.component.d.ts +7 -1
- package/lib/message-input/message-input.component.d.ts +4 -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 -2
- package/public-api.d.ts +1 -0
- package/src/assets/i18n/en.ts +4 -0
- package/src/assets/version.ts +1 -1
|
@@ -1,9 +1,9 @@
|
|
|
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, of, Subject } from 'rxjs';
|
|
4
|
+
import { BehaviorSubject, ReplaySubject, combineLatest, of, Subject } 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
8
|
import * as i10 from '@ngx-translate/core';
|
|
9
9
|
import { TranslateModule } from '@ngx-translate/core';
|
|
@@ -16,7 +16,7 @@ import transliterate from '@stream-io/transliterate';
|
|
|
16
16
|
import * as i5 from 'angular-mentions';
|
|
17
17
|
import { MentionModule } from 'angular-mentions';
|
|
18
18
|
|
|
19
|
-
const version = '2.
|
|
19
|
+
const version = '2.11.0';
|
|
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) => {
|
|
153
153
|
const clientSideId = `${user.id}-${v4()}`;
|
|
154
154
|
return {
|
|
155
155
|
__html: text,
|
|
@@ -163,6 +163,7 @@ const createMessagePreview = (user, text, attachments, mentionedUsers) => {
|
|
|
163
163
|
user,
|
|
164
164
|
attachments,
|
|
165
165
|
mentioned_users: mentionedUsers,
|
|
166
|
+
parent_id: parentId,
|
|
166
167
|
};
|
|
167
168
|
};
|
|
168
169
|
|
|
@@ -188,31 +189,50 @@ class ChannelService {
|
|
|
188
189
|
this.activeChannelMessagesSubject = new BehaviorSubject([]);
|
|
189
190
|
this.hasMoreChannelsSubject = new ReplaySubject(1);
|
|
190
191
|
this.activeChannelSubscriptions = [];
|
|
192
|
+
this.activeParentMessageIdSubject = new BehaviorSubject(undefined);
|
|
193
|
+
this.activeThreadMessagesSubject = new BehaviorSubject([]);
|
|
194
|
+
this.messagePageSize = 25;
|
|
191
195
|
this.channelListSetter = (channels) => {
|
|
192
196
|
this.channelsSubject.next(channels);
|
|
193
197
|
};
|
|
194
198
|
this.messageListSetter = (messages) => {
|
|
195
199
|
this.activeChannelMessagesSubject.next(messages);
|
|
196
200
|
};
|
|
201
|
+
this.threadListSetter = (messages) => {
|
|
202
|
+
this.activeThreadMessagesSubject.next(messages);
|
|
203
|
+
};
|
|
204
|
+
this.parentMessageSetter = (message) => {
|
|
205
|
+
this.activeParentMessageIdSubject.next(message === null || message === void 0 ? void 0 : message.id);
|
|
206
|
+
};
|
|
197
207
|
this.channels$ = this.channelsSubject.asObservable();
|
|
198
208
|
this.activeChannel$ = this.activeChannelSubject.asObservable();
|
|
199
209
|
this.activeChannelMessages$ = this.activeChannelMessagesSubject.pipe(map((messages) => {
|
|
200
210
|
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
|
-
});
|
|
211
|
+
return messages.map((message) => this.transformToStreamMessage(message, channel));
|
|
214
212
|
}));
|
|
215
213
|
this.hasMoreChannels$ = this.hasMoreChannelsSubject.asObservable();
|
|
214
|
+
this.activeParentMessageId$ =
|
|
215
|
+
this.activeParentMessageIdSubject.asObservable();
|
|
216
|
+
this.activeThreadMessages$ = this.activeThreadMessagesSubject.pipe(map((messages) => {
|
|
217
|
+
const channel = this.activeChannelSubject.getValue();
|
|
218
|
+
return messages.map((message) => this.transformToStreamMessage(message, channel));
|
|
219
|
+
}));
|
|
220
|
+
this.activeParentMessage$ = combineLatest([
|
|
221
|
+
this.activeChannelMessages$,
|
|
222
|
+
this.activeParentMessageId$,
|
|
223
|
+
]).pipe(map(([messages, parentMessageId]) => {
|
|
224
|
+
if (!parentMessageId) {
|
|
225
|
+
return undefined;
|
|
226
|
+
}
|
|
227
|
+
else {
|
|
228
|
+
return messages.find((m) => m.id === parentMessageId);
|
|
229
|
+
}
|
|
230
|
+
}), shareReplay());
|
|
231
|
+
this.chatClientService.connectionState$
|
|
232
|
+
.pipe(filter((s) => s === 'online'))
|
|
233
|
+
.subscribe(() => {
|
|
234
|
+
void this.setAsActiveParentMessage(undefined);
|
|
235
|
+
});
|
|
216
236
|
}
|
|
217
237
|
setAsActiveChannel(channel) {
|
|
218
238
|
const prevActiveChannel = this.activeChannelSubject.getValue();
|
|
@@ -226,25 +246,61 @@ class ChannelService {
|
|
|
226
246
|
void channel.markRead();
|
|
227
247
|
}
|
|
228
248
|
this.activeChannelMessagesSubject.next([...channel.state.messages]);
|
|
249
|
+
this.activeParentMessageIdSubject.next(undefined);
|
|
250
|
+
this.activeThreadMessagesSubject.next([]);
|
|
251
|
+
}
|
|
252
|
+
setAsActiveParentMessage(message) {
|
|
253
|
+
var _a;
|
|
254
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
255
|
+
if (!message) {
|
|
256
|
+
this.activeParentMessageIdSubject.next(undefined);
|
|
257
|
+
this.activeThreadMessagesSubject.next([]);
|
|
258
|
+
}
|
|
259
|
+
else {
|
|
260
|
+
this.activeParentMessageIdSubject.next(message.id);
|
|
261
|
+
const activeChannel = this.activeChannelSubject.getValue();
|
|
262
|
+
const result = yield (activeChannel === null || activeChannel === void 0 ? void 0 : activeChannel.getReplies(message.id, {
|
|
263
|
+
limit: (_a = this.options) === null || _a === void 0 ? void 0 : _a.message_limit,
|
|
264
|
+
}));
|
|
265
|
+
this.activeThreadMessagesSubject.next((result === null || result === void 0 ? void 0 : result.messages) || []);
|
|
266
|
+
}
|
|
267
|
+
});
|
|
229
268
|
}
|
|
269
|
+
// load more thread replies
|
|
230
270
|
loadMoreMessages() {
|
|
231
|
-
var _a, _b, _c, _d;
|
|
271
|
+
var _a, _b, _c, _d, _e;
|
|
232
272
|
return __awaiter(this, void 0, void 0, function* () {
|
|
233
273
|
const activeChnannel = this.activeChannelSubject.getValue();
|
|
234
274
|
const lastMessageId = (_a = this.activeChannelMessagesSubject.getValue()[0]) === null || _a === void 0 ? void 0 : _a.id;
|
|
235
275
|
yield (activeChnannel === null || activeChnannel === void 0 ? void 0 : activeChnannel.query({
|
|
236
|
-
messages: { limit:
|
|
276
|
+
messages: { limit: (_b = this.options) === null || _b === void 0 ? void 0 : _b.message_limit, id_lt: lastMessageId },
|
|
237
277
|
members: { limit: 0 },
|
|
238
278
|
watchers: { limit: 0 },
|
|
239
279
|
}));
|
|
240
|
-
if (((
|
|
241
|
-
((
|
|
280
|
+
if (((_c = activeChnannel === null || activeChnannel === void 0 ? void 0 : activeChnannel.data) === null || _c === void 0 ? void 0 : _c.id) ===
|
|
281
|
+
((_e = (_d = this.activeChannelSubject.getValue()) === null || _d === void 0 ? void 0 : _d.data) === null || _e === void 0 ? void 0 : _e.id)) {
|
|
242
282
|
this.activeChannelMessagesSubject.next([
|
|
243
283
|
...activeChnannel.state.messages,
|
|
244
284
|
]);
|
|
245
285
|
}
|
|
246
286
|
});
|
|
247
287
|
}
|
|
288
|
+
loadMoreThreadReplies() {
|
|
289
|
+
var _a, _b;
|
|
290
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
291
|
+
const activeChnannel = this.activeChannelSubject.getValue();
|
|
292
|
+
const parentMessageId = this.activeParentMessageIdSubject.getValue();
|
|
293
|
+
if (!parentMessageId) {
|
|
294
|
+
return;
|
|
295
|
+
}
|
|
296
|
+
const lastMessageId = (_a = this.activeThreadMessagesSubject.getValue()[0]) === null || _a === void 0 ? void 0 : _a.id;
|
|
297
|
+
yield (activeChnannel === null || activeChnannel === void 0 ? void 0 : activeChnannel.getReplies(parentMessageId, {
|
|
298
|
+
limit: (_b = this.options) === null || _b === void 0 ? void 0 : _b.message_limit,
|
|
299
|
+
id_lt: lastMessageId,
|
|
300
|
+
}));
|
|
301
|
+
this.activeThreadMessagesSubject.next((activeChnannel === null || activeChnannel === void 0 ? void 0 : activeChnannel.state.threads[parentMessageId]) || []);
|
|
302
|
+
});
|
|
303
|
+
}
|
|
248
304
|
init(filters, sort, options) {
|
|
249
305
|
return __awaiter(this, void 0, void 0, function* () {
|
|
250
306
|
this.filters = filters;
|
|
@@ -254,7 +310,7 @@ class ChannelService {
|
|
|
254
310
|
state: true,
|
|
255
311
|
presence: true,
|
|
256
312
|
watch: true,
|
|
257
|
-
message_limit:
|
|
313
|
+
message_limit: this.messagePageSize,
|
|
258
314
|
};
|
|
259
315
|
this.sort = sort || { last_message_at: -1, updated_at: -1 };
|
|
260
316
|
yield this.queryChannels();
|
|
@@ -264,6 +320,8 @@ class ChannelService {
|
|
|
264
320
|
reset() {
|
|
265
321
|
this.activeChannelMessagesSubject.next([]);
|
|
266
322
|
this.activeChannelSubject.next(undefined);
|
|
323
|
+
this.activeParentMessageIdSubject.next(undefined);
|
|
324
|
+
this.activeThreadMessagesSubject.next([]);
|
|
267
325
|
this.channelsSubject.next(undefined);
|
|
268
326
|
}
|
|
269
327
|
loadMoreChannels() {
|
|
@@ -287,9 +345,9 @@ class ChannelService {
|
|
|
287
345
|
.getValue()) === null || _a === void 0 ? void 0 : _a.deleteReaction(messageId, reactionType));
|
|
288
346
|
});
|
|
289
347
|
}
|
|
290
|
-
sendMessage(text, attachments = [], mentionedUsers = []) {
|
|
348
|
+
sendMessage(text, attachments = [], mentionedUsers = [], parentId = undefined) {
|
|
291
349
|
return __awaiter(this, void 0, void 0, function* () {
|
|
292
|
-
const preview = createMessagePreview(this.chatClientService.chatClient.user, text, attachments, mentionedUsers);
|
|
350
|
+
const preview = createMessagePreview(this.chatClientService.chatClient.user, text, attachments, mentionedUsers, parentId);
|
|
293
351
|
const channel = this.activeChannelSubject.getValue();
|
|
294
352
|
preview.readBy = [];
|
|
295
353
|
channel.state.addMessageSorted(preview, true);
|
|
@@ -373,11 +431,25 @@ class ChannelService {
|
|
|
373
431
|
const response = yield channel.sendAction(messageId, formData);
|
|
374
432
|
if (response === null || response === void 0 ? void 0 : response.message) {
|
|
375
433
|
channel.state.addMessageSorted(Object.assign(Object.assign({}, response.message), { status: 'received' }));
|
|
376
|
-
|
|
434
|
+
const isThreadReply = !!response.message.parent_id;
|
|
435
|
+
isThreadReply
|
|
436
|
+
? this.activeThreadMessagesSubject.next([
|
|
437
|
+
...channel.state.threads[response.message.parent_id],
|
|
438
|
+
])
|
|
439
|
+
: this.activeChannelMessagesSubject.next([...channel.state.messages]);
|
|
377
440
|
}
|
|
378
441
|
else {
|
|
379
442
|
channel.state.removeMessage({ id: messageId });
|
|
380
|
-
this.activeChannelMessagesSubject
|
|
443
|
+
if (this.activeChannelMessagesSubject
|
|
444
|
+
.getValue()
|
|
445
|
+
.find((m) => m.id === messageId)) {
|
|
446
|
+
this.activeChannelMessagesSubject.next([...channel.state.messages]);
|
|
447
|
+
}
|
|
448
|
+
else if (this.activeThreadMessagesSubject
|
|
449
|
+
.getValue()
|
|
450
|
+
.find((m) => m.id === messageId)) {
|
|
451
|
+
this.activeThreadMessagesSubject.next(channel.state.threads[this.activeParentMessageIdSubject.getValue()]);
|
|
452
|
+
}
|
|
381
453
|
}
|
|
382
454
|
});
|
|
383
455
|
}
|
|
@@ -385,17 +457,27 @@ class ChannelService {
|
|
|
385
457
|
var _a;
|
|
386
458
|
return __awaiter(this, void 0, void 0, function* () {
|
|
387
459
|
const channel = this.activeChannelSubject.getValue();
|
|
388
|
-
|
|
460
|
+
const isThreadReply = !!preview.parent_id;
|
|
461
|
+
isThreadReply
|
|
462
|
+
? this.activeThreadMessagesSubject.next([
|
|
463
|
+
...channel.state.threads[preview.parent_id],
|
|
464
|
+
])
|
|
465
|
+
: this.activeChannelMessagesSubject.next([...channel.state.messages]);
|
|
389
466
|
try {
|
|
390
467
|
const response = yield channel.sendMessage({
|
|
391
468
|
text: preview.text,
|
|
392
469
|
attachments: preview.attachments,
|
|
393
470
|
mentioned_users: (_a = preview.mentioned_users) === null || _a === void 0 ? void 0 : _a.map((u) => u.id),
|
|
394
471
|
id: preview.id,
|
|
472
|
+
parent_id: preview.parent_id,
|
|
395
473
|
});
|
|
396
474
|
if (response === null || response === void 0 ? void 0 : response.message) {
|
|
397
475
|
channel.state.addMessageSorted(Object.assign(Object.assign({}, response.message), { status: 'received' }), true);
|
|
398
|
-
|
|
476
|
+
isThreadReply
|
|
477
|
+
? this.activeThreadMessagesSubject.next([
|
|
478
|
+
...channel.state.threads[preview.parent_id],
|
|
479
|
+
])
|
|
480
|
+
: this.activeChannelMessagesSubject.next([...channel.state.messages]);
|
|
399
481
|
}
|
|
400
482
|
}
|
|
401
483
|
catch (error) {
|
|
@@ -404,7 +486,11 @@ class ChannelService {
|
|
|
404
486
|
? JSON.parse(stringError)
|
|
405
487
|
: {};
|
|
406
488
|
channel.state.addMessageSorted(Object.assign(Object.assign({}, preview), { errorStatusCode: parsedError.status || undefined, status: 'failed' }), true);
|
|
407
|
-
|
|
489
|
+
isThreadReply
|
|
490
|
+
? this.activeThreadMessagesSubject.next([
|
|
491
|
+
...channel.state.threads[preview.parent_id],
|
|
492
|
+
])
|
|
493
|
+
: this.activeChannelMessagesSubject.next([...channel.state.messages]);
|
|
408
494
|
}
|
|
409
495
|
});
|
|
410
496
|
}
|
|
@@ -482,9 +568,15 @@ class ChannelService {
|
|
|
482
568
|
}
|
|
483
569
|
}
|
|
484
570
|
watchForActiveChannelEvents(channel) {
|
|
485
|
-
this.activeChannelSubscriptions.push(channel.on('message.new', () => {
|
|
571
|
+
this.activeChannelSubscriptions.push(channel.on('message.new', (event) => {
|
|
486
572
|
this.ngZone.run(() => {
|
|
487
|
-
|
|
573
|
+
event.message && event.message.parent_id
|
|
574
|
+
? this.activeThreadMessagesSubject.next([
|
|
575
|
+
...channel.state.threads[event.message.parent_id],
|
|
576
|
+
])
|
|
577
|
+
: this.activeChannelMessagesSubject.next([
|
|
578
|
+
...channel.state.messages,
|
|
579
|
+
]);
|
|
488
580
|
this.activeChannel$.pipe(first()).subscribe((c) => {
|
|
489
581
|
if (this.canSendReadEvents) {
|
|
490
582
|
void (c === null || c === void 0 ? void 0 : c.markRead());
|
|
@@ -513,19 +605,27 @@ class ChannelService {
|
|
|
513
605
|
}
|
|
514
606
|
messageUpdated(event) {
|
|
515
607
|
this.ngZone.run(() => {
|
|
516
|
-
const
|
|
608
|
+
const isThreadReply = event.message && event.message.parent_id;
|
|
609
|
+
const messages = isThreadReply
|
|
610
|
+
? this.activeThreadMessagesSubject.getValue()
|
|
611
|
+
: this.activeChannelMessagesSubject.getValue();
|
|
517
612
|
const messageIndex = messages.findIndex((m) => { var _a; return m.id === ((_a = event.message) === null || _a === void 0 ? void 0 : _a.id); });
|
|
518
613
|
if (messageIndex !== -1 && event.message) {
|
|
519
614
|
messages[messageIndex] = event.message;
|
|
520
|
-
|
|
615
|
+
isThreadReply
|
|
616
|
+
? this.activeThreadMessagesSubject.next([...messages])
|
|
617
|
+
: this.activeChannelMessagesSubject.next([...messages]);
|
|
521
618
|
}
|
|
522
619
|
});
|
|
523
620
|
}
|
|
524
621
|
messageReactionEventReceived(e) {
|
|
525
622
|
this.ngZone.run(() => {
|
|
526
623
|
var _a, _b, _c, _d;
|
|
624
|
+
const isThreadMessage = e.message && e.message.parent_id;
|
|
527
625
|
let messages;
|
|
528
|
-
|
|
626
|
+
(isThreadMessage
|
|
627
|
+
? this.activeThreadMessages$
|
|
628
|
+
: this.activeChannelMessages$)
|
|
529
629
|
.pipe(first())
|
|
530
630
|
.subscribe((m) => (messages = m));
|
|
531
631
|
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 +636,9 @@ class ChannelService {
|
|
|
536
636
|
message.reaction_scores = Object.assign({}, (_b = e.message) === null || _b === void 0 ? void 0 : _b.reaction_scores);
|
|
537
637
|
message.latest_reactions = [...(((_c = e.message) === null || _c === void 0 ? void 0 : _c.latest_reactions) || [])];
|
|
538
638
|
message.own_reactions = [...(((_d = e.message) === null || _d === void 0 ? void 0 : _d.own_reactions) || [])];
|
|
539
|
-
|
|
639
|
+
isThreadMessage
|
|
640
|
+
? this.activeThreadMessagesSubject.next([...messages])
|
|
641
|
+
: this.activeChannelMessagesSubject.next([...messages]);
|
|
540
642
|
});
|
|
541
643
|
}
|
|
542
644
|
formatMessage(message) {
|
|
@@ -584,7 +686,7 @@ class ChannelService {
|
|
|
584
686
|
case 'message.new': {
|
|
585
687
|
this.ngZone.run(() => {
|
|
586
688
|
if (this.customNewMessageHandler) {
|
|
587
|
-
this.customNewMessageHandler(event, channel, this.channelListSetter, this.messageListSetter);
|
|
689
|
+
this.customNewMessageHandler(event, channel, this.channelListSetter, this.messageListSetter, this.threadListSetter, this.parentMessageSetter);
|
|
588
690
|
}
|
|
589
691
|
else {
|
|
590
692
|
this.handleNewMessage(event, channel);
|
|
@@ -595,7 +697,7 @@ class ChannelService {
|
|
|
595
697
|
case 'channel.hidden': {
|
|
596
698
|
this.ngZone.run(() => {
|
|
597
699
|
if (this.customChannelHiddenHandler) {
|
|
598
|
-
this.customChannelHiddenHandler(event, channel, this.channelListSetter, this.messageListSetter);
|
|
700
|
+
this.customChannelHiddenHandler(event, channel, this.channelListSetter, this.messageListSetter, this.threadListSetter, this.parentMessageSetter);
|
|
599
701
|
}
|
|
600
702
|
else {
|
|
601
703
|
this.handleChannelHidden(event);
|
|
@@ -606,7 +708,7 @@ class ChannelService {
|
|
|
606
708
|
case 'channel.deleted': {
|
|
607
709
|
this.ngZone.run(() => {
|
|
608
710
|
if (this.customChannelDeletedHandler) {
|
|
609
|
-
this.customChannelDeletedHandler(event, channel, this.channelListSetter, this.messageListSetter);
|
|
711
|
+
this.customChannelDeletedHandler(event, channel, this.channelListSetter, this.messageListSetter, this.threadListSetter, this.parentMessageSetter);
|
|
610
712
|
}
|
|
611
713
|
else {
|
|
612
714
|
this.handleChannelDeleted(event);
|
|
@@ -617,7 +719,7 @@ class ChannelService {
|
|
|
617
719
|
case 'channel.visible': {
|
|
618
720
|
this.ngZone.run(() => {
|
|
619
721
|
if (this.customChannelVisibleHandler) {
|
|
620
|
-
this.customChannelVisibleHandler(event, channel, this.channelListSetter, this.messageListSetter);
|
|
722
|
+
this.customChannelVisibleHandler(event, channel, this.channelListSetter, this.messageListSetter, this.threadListSetter, this.parentMessageSetter);
|
|
621
723
|
}
|
|
622
724
|
else {
|
|
623
725
|
this.handleChannelVisible(event, channel);
|
|
@@ -628,7 +730,7 @@ class ChannelService {
|
|
|
628
730
|
case 'channel.updated': {
|
|
629
731
|
this.ngZone.run(() => {
|
|
630
732
|
if (this.customChannelUpdatedHandler) {
|
|
631
|
-
this.customChannelUpdatedHandler(event, channel, this.channelListSetter, this.messageListSetter);
|
|
733
|
+
this.customChannelUpdatedHandler(event, channel, this.channelListSetter, this.messageListSetter, this.threadListSetter, this.parentMessageSetter);
|
|
632
734
|
}
|
|
633
735
|
else {
|
|
634
736
|
this.handleChannelUpdate(event);
|
|
@@ -639,7 +741,7 @@ class ChannelService {
|
|
|
639
741
|
case 'channel.truncated': {
|
|
640
742
|
this.ngZone.run(() => {
|
|
641
743
|
if (this.customChannelTruncatedHandler) {
|
|
642
|
-
this.customChannelTruncatedHandler(event, channel, this.channelListSetter, this.messageListSetter);
|
|
744
|
+
this.customChannelTruncatedHandler(event, channel, this.channelListSetter, this.messageListSetter, this.threadListSetter, this.parentMessageSetter);
|
|
643
745
|
}
|
|
644
746
|
else {
|
|
645
747
|
this.handleChannelTruncate(event);
|
|
@@ -679,6 +781,7 @@ class ChannelService {
|
|
|
679
781
|
}
|
|
680
782
|
}
|
|
681
783
|
}
|
|
784
|
+
// truncate active thread as well
|
|
682
785
|
handleChannelTruncate(event) {
|
|
683
786
|
var _a, _b;
|
|
684
787
|
const channelIndex = this.channels.findIndex((c) => c.cid === event.channel.cid);
|
|
@@ -690,6 +793,8 @@ class ChannelService {
|
|
|
690
793
|
channel.state.messages = [];
|
|
691
794
|
this.activeChannelSubject.next(channel);
|
|
692
795
|
this.activeChannelMessagesSubject.next([]);
|
|
796
|
+
this.activeParentMessageIdSubject.next(undefined);
|
|
797
|
+
this.activeThreadMessagesSubject.next([]);
|
|
693
798
|
}
|
|
694
799
|
}
|
|
695
800
|
}
|
|
@@ -705,6 +810,20 @@ class ChannelService {
|
|
|
705
810
|
const capabilites = (_a = channel.data) === null || _a === void 0 ? void 0 : _a.own_capabilities;
|
|
706
811
|
return capabilites.indexOf('read-events') !== -1;
|
|
707
812
|
}
|
|
813
|
+
transformToStreamMessage(message, channel) {
|
|
814
|
+
const isThreadMessage = !!message.parent_id;
|
|
815
|
+
if (this.isStreamMessage(message) &&
|
|
816
|
+
this.isFormatMessageResponse(message)) {
|
|
817
|
+
return message;
|
|
818
|
+
}
|
|
819
|
+
else if (this.isFormatMessageResponse(message)) {
|
|
820
|
+
return Object.assign(Object.assign({}, message), { readBy: isThreadMessage ? [] : getReadBy(message, channel) });
|
|
821
|
+
}
|
|
822
|
+
else {
|
|
823
|
+
const formatMessage = this.formatMessage(message);
|
|
824
|
+
return Object.assign(Object.assign({}, formatMessage), { readBy: isThreadMessage ? [] : getReadBy(formatMessage, channel) });
|
|
825
|
+
}
|
|
826
|
+
}
|
|
708
827
|
}
|
|
709
828
|
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
829
|
ChannelService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: ChannelService, providedIn: 'root' });
|
|
@@ -1017,6 +1136,7 @@ const en = {
|
|
|
1017
1136
|
Flag: 'Flag',
|
|
1018
1137
|
'Message Failed': 'Message Failed',
|
|
1019
1138
|
'Message Failed · Unauthorized': 'Message Failed · Unauthorized',
|
|
1139
|
+
'Message Failed · Click to try again': 'Message Failed · Click to try again',
|
|
1020
1140
|
'Message deleted': 'Message deleted',
|
|
1021
1141
|
'Message has been successfully flagged': 'Message has been successfully flagged',
|
|
1022
1142
|
'Message pinned': 'Message pinned',
|
|
@@ -1067,6 +1187,7 @@ const en = {
|
|
|
1067
1187
|
test: 'success',
|
|
1068
1188
|
'Sending links is not allowed in this conversation': 'Sending links is not allowed in this conversation',
|
|
1069
1189
|
"You can't send messages in this channel": "You can't send messages in this channel",
|
|
1190
|
+
"You can't send thread replies in this channel": "You can't send thread replies in this channel",
|
|
1070
1191
|
'Unsupported file type: {{type}}': 'Unsupported file type: {{type}}',
|
|
1071
1192
|
},
|
|
1072
1193
|
};
|
|
@@ -1123,7 +1244,7 @@ class IconComponent {
|
|
|
1123
1244
|
constructor() { }
|
|
1124
1245
|
}
|
|
1125
1246
|
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: i10.TranslateDirective, selector: "[translate],[ngx-translate]", inputs: ["translate", "translateParams"] }] });
|
|
1247
|
+
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 data-testid=\"close-no-outline\"\n *ngIf=\"icon === 'close-no-outline'\"\n height=\"10\"\n width=\"10\"\n xmlns=\"http://www.w3.org/2000/svg\"\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: i10.TranslateDirective, selector: "[translate],[ngx-translate]", inputs: ["translate", "translateParams"] }] });
|
|
1127
1248
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: IconComponent, decorators: [{
|
|
1128
1249
|
type: Component,
|
|
1129
1250
|
args: [{
|
|
@@ -1301,6 +1422,7 @@ class MessageInputComponent {
|
|
|
1301
1422
|
this.componentFactoryResolver = componentFactoryResolver;
|
|
1302
1423
|
this.cdRef = cdRef;
|
|
1303
1424
|
this.chatClient = chatClient;
|
|
1425
|
+
this.mode = 'main';
|
|
1304
1426
|
this.messageUpdate = new EventEmitter();
|
|
1305
1427
|
this.textareaValue = '';
|
|
1306
1428
|
this.mentionedUsers = [];
|
|
@@ -1321,11 +1443,8 @@ class MessageInputComponent {
|
|
|
1321
1443
|
this.isFileUploadAuthorized =
|
|
1322
1444
|
capabilities.indexOf('upload-file') !== -1;
|
|
1323
1445
|
this.canSendLinks = capabilities.indexOf('send-links') !== -1;
|
|
1324
|
-
this.
|
|
1325
|
-
|
|
1326
|
-
this.cdRef.detectChanges();
|
|
1327
|
-
this.initTextarea();
|
|
1328
|
-
}
|
|
1446
|
+
this.channel = channel;
|
|
1447
|
+
this.setCanSendMessages();
|
|
1329
1448
|
}
|
|
1330
1449
|
}));
|
|
1331
1450
|
this.subscriptions.push(this.chatClient.appSettings$.subscribe((appSettings) => (this.appSettings = appSettings)));
|
|
@@ -1377,6 +1496,9 @@ class MessageInputComponent {
|
|
|
1377
1496
|
if (changes.mentionScope) {
|
|
1378
1497
|
this.configService.mentionScope = this.mentionScope;
|
|
1379
1498
|
}
|
|
1499
|
+
if (changes.mode) {
|
|
1500
|
+
this.setCanSendMessages();
|
|
1501
|
+
}
|
|
1380
1502
|
}
|
|
1381
1503
|
ngOnDestroy() {
|
|
1382
1504
|
this.subscriptions.forEach((s) => s.unsubscribe());
|
|
@@ -1406,10 +1528,16 @@ class MessageInputComponent {
|
|
|
1406
1528
|
if (!this.isUpdate) {
|
|
1407
1529
|
this.textareaValue = '';
|
|
1408
1530
|
}
|
|
1531
|
+
let parentMessageId = undefined;
|
|
1532
|
+
if (this.mode === 'thread') {
|
|
1533
|
+
this.channelService.activeParentMessageId$
|
|
1534
|
+
.pipe(first())
|
|
1535
|
+
.subscribe((id) => (parentMessageId = id));
|
|
1536
|
+
}
|
|
1409
1537
|
try {
|
|
1410
1538
|
yield (this.isUpdate
|
|
1411
1539
|
? this.channelService.updateMessage(Object.assign(Object.assign({}, this.message), { text: text, attachments: attachments }))
|
|
1412
|
-
: this.channelService.sendMessage(text, attachments, this.mentionedUsers));
|
|
1540
|
+
: this.channelService.sendMessage(text, attachments, this.mentionedUsers, parentMessageId));
|
|
1413
1541
|
this.messageUpdate.emit();
|
|
1414
1542
|
if (!this.isUpdate) {
|
|
1415
1543
|
this.attachmentService.resetAttachmentUploads();
|
|
@@ -1503,9 +1631,24 @@ class MessageInputComponent {
|
|
|
1503
1631
|
return isValid;
|
|
1504
1632
|
});
|
|
1505
1633
|
}
|
|
1634
|
+
setCanSendMessages() {
|
|
1635
|
+
var _a, _b;
|
|
1636
|
+
const capabilities = (_b = (_a = this.channel) === null || _a === void 0 ? void 0 : _a.data) === null || _b === void 0 ? void 0 : _b.own_capabilities;
|
|
1637
|
+
if (!capabilities) {
|
|
1638
|
+
this.canSendMessages = false;
|
|
1639
|
+
}
|
|
1640
|
+
else {
|
|
1641
|
+
this.canSendMessages =
|
|
1642
|
+
capabilities.indexOf(this.mode === 'main' ? 'send-message' : 'send-reply') !== -1;
|
|
1643
|
+
}
|
|
1644
|
+
if (this.isViewInited) {
|
|
1645
|
+
this.cdRef.detectChanges();
|
|
1646
|
+
this.initTextarea();
|
|
1647
|
+
}
|
|
1648
|
+
}
|
|
1506
1649
|
}
|
|
1507
1650
|
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
|
|
1651
|
+
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>\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: AttachmentPreviewListComponent, selector: "stream-attachment-preview-list" }, { type: IconComponent, selector: "stream-icon", inputs: ["icon", "size"] }], 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": i10.TranslatePipe } });
|
|
1509
1652
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: MessageInputComponent, decorators: [{
|
|
1510
1653
|
type: Component,
|
|
1511
1654
|
args: [{
|
|
@@ -1527,6 +1670,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImpor
|
|
|
1527
1670
|
type: Input
|
|
1528
1671
|
}], commandAutocompleteItemTemplate: [{
|
|
1529
1672
|
type: Input
|
|
1673
|
+
}], mode: [{
|
|
1674
|
+
type: Input
|
|
1530
1675
|
}], acceptedFileTypes: [{
|
|
1531
1676
|
type: Input
|
|
1532
1677
|
}], isMultipleFileUploadEnabled: [{
|
|
@@ -1746,7 +1891,7 @@ class MessageActionsBoxComponent {
|
|
|
1746
1891
|
}
|
|
1747
1892
|
}
|
|
1748
1893
|
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: i10.TranslateDirective, selector: "[translate],[ngx-translate]", inputs: ["translate", "translateParams"] }], pipes: { "translate": i10.TranslatePipe } });
|
|
1894
|
+
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: i10.TranslateDirective, selector: "[translate],[ngx-translate]", inputs: ["translate", "translateParams"] }], pipes: { "translate": i10.TranslatePipe } });
|
|
1750
1895
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: MessageActionsBoxComponent, decorators: [{
|
|
1751
1896
|
type: Component,
|
|
1752
1897
|
args: [{
|
|
@@ -1779,10 +1924,11 @@ class ChannelComponent {
|
|
|
1779
1924
|
this.subscriptions = [];
|
|
1780
1925
|
this.isError$ = this.channelService.channels$.pipe(map(() => false), catchError(() => of(true)), startWith(false));
|
|
1781
1926
|
this.isInitializing$ = this.channelService.channels$.pipe(map((channels) => !channels), catchError(() => of(false)));
|
|
1927
|
+
this.isActiveThread$ = this.channelService.activeParentMessageId$.pipe(map((id) => !!id));
|
|
1782
1928
|
}
|
|
1783
1929
|
}
|
|
1784
1930
|
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 } });
|
|
1931
|
+
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
1932
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: ChannelComponent, decorators: [{
|
|
1787
1933
|
type: Component,
|
|
1788
1934
|
args: [{
|
|
@@ -2276,6 +2422,7 @@ class MessageComponent {
|
|
|
2276
2422
|
this.chatClientService = chatClientService;
|
|
2277
2423
|
this.channelService = channelService;
|
|
2278
2424
|
this.enabledMessageActions = [];
|
|
2425
|
+
this.mode = 'main';
|
|
2279
2426
|
this.isActionBoxOpen = false;
|
|
2280
2427
|
this.isReactionSelectorOpen = false;
|
|
2281
2428
|
this.isPressedOnMobile = false;
|
|
@@ -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,14 @@ 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
|
+
}
|
|
2379
2535
|
resendMessage() {
|
|
2380
2536
|
void this.channelService.resendMessage(this.message);
|
|
2381
2537
|
}
|
|
@@ -2397,9 +2553,12 @@ class MessageComponent {
|
|
|
2397
2553
|
};
|
|
2398
2554
|
window.addEventListener('click', eventHandler);
|
|
2399
2555
|
}
|
|
2556
|
+
setAsActiveParentMessage() {
|
|
2557
|
+
void this.channelService.setAsActiveParentMessage(this.message);
|
|
2558
|
+
}
|
|
2400
2559
|
}
|
|
2401
2560
|
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 } });
|
|
2561
|
+
MessageComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.5", type: MessageComponent, selector: "stream-message", inputs: { messageInputTemplate: "messageInputTemplate", mentionTemplate: "mentionTemplate", message: "message", enabledMessageActions: "enabledMessageActions", areReactionsEnabled: "areReactionsEnabled", canReactToMessage: "canReactToMessage", isLastSentMessage: "isLastSentMessage", canReceiveReadEvents: "canReceiveReadEvents", mode: "mode" }, viewQueries: [{ propertyName: "container", first: true, predicate: ["container"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div\n #container\n class=\"str-chat__message-simple str-chat__message str-chat__message--{{\n message?.type\n }} str-chat__message--{{ message?.status }} {{\n message?.text ? 'str-chat__message--has-text' : 'has-no-text'\n }}\"\n [class.str-chat__message--me]=\"isSentByCurrentUser\"\n [class.str-chat__message-simple--me]=\"isSentByCurrentUser\"\n [class.mobile-press]=\"isPressedOnMobile\"\n [class.str-chat__message--has-attachment]=\"hasAttachment\"\n [class.str-chat__message--with-reactions]=\"\n areReactionsEnabled !== false && hasReactions\n \"\n data-testid=\"message-container\"\n>\n <ng-container *ngIf=\"!message?.deleted_at; else deletedMessage\">\n <ng-container *ngIf=\"message?.type !== 'system'; else systemMessage\">\n <ng-container\n *ngIf=\"\n isSentByCurrentUser &&\n ((isLastSentMessage && message?.status === 'received') ||\n message?.status === 'sending')\n \"\n >\n <ng-container *ngIf=\"message?.status === 'sending'; else sentStatus\">\n <ng-container *ngTemplateOutlet=\"sendingStatus\"></ng-container>\n </ng-container>\n <ng-template #sentStatus>\n <ng-container\n *ngIf=\"\n mode === 'main' &&\n isMessageDeliveredAndRead &&\n canDisplayReadStatus;\n else deliveredStatus\n \"\n >\n <ng-container *ngTemplateOutlet=\"readStatus\"></ng-container>\n </ng-container>\n </ng-template>\n </ng-container>\n <stream-avatar\n data-testid=\"avatar\"\n class=\"str-chat-angular__avatar-host\"\n [imageUrl]=\"message?.user?.image\"\n [name]=\"message?.user?.name || message?.user?.id\"\n ></stream-avatar>\n <div class=\"str-chat__message-inner\">\n <div\n class=\"str-chat__message-simple__actions\"\n data-testid=\"message-options\"\n *ngIf=\"areOptionsVisible\"\n >\n <div\n data-testid=\"message-actions-container\"\n class=\"\n str-chat__message-simple__actions__action\n str-chat__message-simple__actions__action--options\n \"\n [class.str-chat-angular__message-simple__actions__action--options--editing]=\"\n isEditing\n \"\n >\n <stream-message-actions-box\n [isOpen]=\"isActionBoxOpen\"\n [isMine]=\"isSentByCurrentUser\"\n [enabledActions]=\"enabledMessageActions\"\n [message]=\"message\"\n (displayedActionsCount)=\"visibleMessageActionsCount = $event\"\n (isEditing)=\"isEditing = $event; isActionBoxOpen = !isEditing\"\n [messageInputTemplate]=\"messageInputTemplate\"\n ></stream-message-actions-box>\n <stream-icon\n *ngIf=\"visibleMessageActionsCount > 0\"\n data-testid=\"action-icon\"\n icon=\"action-icon\"\n (keyup.enter)=\"isActionBoxOpen = !isActionBoxOpen\"\n (click)=\"isActionBoxOpen = !isActionBoxOpen\"\n ></stream-icon>\n </div>\n <!-- eslint-disable @angular-eslint/template/conditional-complexity -->\n <div\n *ngIf=\"\n enabledMessageActions.indexOf('send-reply') !== -1 &&\n mode === 'main'\n \"\n class=\"\n str-chat__message-simple__actions__action\n str-chat__message-simple__actions__action--thread\n \"\n data-testid=\"reply-in-thread\"\n (click)=\"setAsActiveParentMessage()\"\n (keyup.enter)=\"setAsActiveParentMessage()\"\n >\n <stream-icon icon=\"reply-in-thread\"></stream-icon>\n </div>\n <div\n *ngIf=\"\n areReactionsEnabled !== false &&\n canReactToMessage !== false &&\n enabledMessageActions.indexOf('send-reaction') !== -1\n \"\n class=\"\n str-chat__message-simple__actions__action\n str-chat__message-simple__actions__action--reactions\n \"\n data-testid=\"reaction-icon\"\n (click)=\"isReactionSelectorOpen = !isReactionSelectorOpen\"\n (keyup.enter)=\"isReactionSelectorOpen = !isReactionSelectorOpen\"\n >\n <stream-icon icon=\"reaction-icon\"></stream-icon>\n </div>\n </div>\n <!-- eslint-enable @angular-eslint/template/conditional-complexity -->\n <stream-message-reactions\n *ngIf=\"areReactionsEnabled !== false\"\n [messageReactionCounts]=\"message?.reaction_counts || {}\"\n [latestReactions]=\"message?.latest_reactions || []\"\n [(isSelectorOpen)]=\"isReactionSelectorOpen\"\n [messageId]=\"message?.id\"\n [ownReactions]=\"message?.own_reactions || []\"\n ></stream-message-reactions>\n <stream-attachment-list\n *ngIf=\"hasAttachment\"\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-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", 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 } });
|
|
2403
2562
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: MessageComponent, decorators: [{
|
|
2404
2563
|
type: Component,
|
|
2405
2564
|
args: [{
|
|
@@ -2423,6 +2582,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImpor
|
|
|
2423
2582
|
type: Input
|
|
2424
2583
|
}], canReceiveReadEvents: [{
|
|
2425
2584
|
type: Input
|
|
2585
|
+
}], mode: [{
|
|
2586
|
+
type: Input
|
|
2426
2587
|
}], container: [{
|
|
2427
2588
|
type: ViewChild,
|
|
2428
2589
|
args: ['container']
|
|
@@ -2716,22 +2877,17 @@ class MessageListComponent {
|
|
|
2716
2877
|
*/
|
|
2717
2878
|
/* eslint-disable-next-line @angular-eslint/no-input-rename */
|
|
2718
2879
|
this.enabledMessageActionsInput = undefined;
|
|
2880
|
+
this.mode = 'main';
|
|
2719
2881
|
this.enabledMessageActions = [];
|
|
2720
2882
|
this.class = 'str-chat-angular__main-panel-inner str-chat-angular__message-list-host';
|
|
2721
2883
|
this.unreadMessageCount = 0;
|
|
2722
2884
|
this.groupStyles = [];
|
|
2723
2885
|
this.authorizedMessageActions = ['flag'];
|
|
2724
2886
|
this.isUserScrolledUpThreshold = 300;
|
|
2725
|
-
this.
|
|
2887
|
+
this.subscriptions = [];
|
|
2888
|
+
this.subscriptions.push(this.channelService.activeChannel$.subscribe((channel) => {
|
|
2726
2889
|
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;
|
|
2890
|
+
this.resetScrollState();
|
|
2735
2891
|
const capabilites = (_a = channel === null || channel === void 0 ? void 0 : channel.data) === null || _a === void 0 ? void 0 : _a.own_capabilities;
|
|
2736
2892
|
if (capabilites) {
|
|
2737
2893
|
this.canReactToMessage = capabilites.indexOf('send-reaction') !== -1;
|
|
@@ -2760,47 +2916,13 @@ class MessageListComponent {
|
|
|
2760
2916
|
this.authorizedMessageActions.push('delete');
|
|
2761
2917
|
this.authorizedMessageActions.push('delete-any');
|
|
2762
2918
|
}
|
|
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++;
|
|
2919
|
+
if (capabilites.indexOf('send-reply') !== -1) {
|
|
2920
|
+
this.authorizedMessageActions.push('send-reply');
|
|
2781
2921
|
}
|
|
2922
|
+
this.setEnabledActions();
|
|
2782
2923
|
}
|
|
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
2924
|
}));
|
|
2803
|
-
this.imageLoadService.imageLoad$.subscribe(() => {
|
|
2925
|
+
this.subscriptions.push(this.imageLoadService.imageLoad$.subscribe(() => {
|
|
2804
2926
|
if (!this.isUserScrolledUp) {
|
|
2805
2927
|
this.scrollToBottom();
|
|
2806
2928
|
// Hacky and unreliable workaround to scroll down after loaded images move the scrollbar
|
|
@@ -2808,12 +2930,27 @@ class MessageListComponent {
|
|
|
2808
2930
|
this.scrollToBottom();
|
|
2809
2931
|
}, 300);
|
|
2810
2932
|
}
|
|
2811
|
-
});
|
|
2933
|
+
}));
|
|
2934
|
+
this.subscriptions.push(this.channelService.activeParentMessage$.subscribe((message) => {
|
|
2935
|
+
if (message &&
|
|
2936
|
+
this.parentMessage &&
|
|
2937
|
+
message.id !== this.parentMessage.id &&
|
|
2938
|
+
this.mode === 'thread') {
|
|
2939
|
+
this.resetScrollState();
|
|
2940
|
+
}
|
|
2941
|
+
this.parentMessage = message;
|
|
2942
|
+
}));
|
|
2943
|
+
}
|
|
2944
|
+
ngOnInit() {
|
|
2945
|
+
this.setMessages$();
|
|
2812
2946
|
}
|
|
2813
2947
|
ngOnChanges(changes) {
|
|
2814
2948
|
if (changes.enabledMessageActionsInput) {
|
|
2815
2949
|
this.setEnabledActions();
|
|
2816
2950
|
}
|
|
2951
|
+
if (changes.mode) {
|
|
2952
|
+
this.setMessages$();
|
|
2953
|
+
}
|
|
2817
2954
|
}
|
|
2818
2955
|
ngAfterViewChecked() {
|
|
2819
2956
|
if (this.hasNewMessages) {
|
|
@@ -2839,6 +2976,9 @@ class MessageListComponent {
|
|
|
2839
2976
|
this.containerHeight = this.scrollContainer.nativeElement.scrollHeight;
|
|
2840
2977
|
}
|
|
2841
2978
|
}
|
|
2979
|
+
ngOnDestroy() {
|
|
2980
|
+
this.subscriptions.forEach((s) => s.unsubscribe());
|
|
2981
|
+
}
|
|
2842
2982
|
trackByMessageId(index, item) {
|
|
2843
2983
|
return item.id;
|
|
2844
2984
|
}
|
|
@@ -2847,6 +2987,7 @@ class MessageListComponent {
|
|
|
2847
2987
|
this.scrollContainer.nativeElement.scrollHeight;
|
|
2848
2988
|
}
|
|
2849
2989
|
scrolled() {
|
|
2990
|
+
var _a, _b;
|
|
2850
2991
|
this.isUserScrolledUp =
|
|
2851
2992
|
this.scrollContainer.nativeElement.scrollHeight -
|
|
2852
2993
|
(this.scrollContainer.nativeElement.scrollTop +
|
|
@@ -2855,14 +2996,22 @@ class MessageListComponent {
|
|
|
2855
2996
|
if (!this.isUserScrolledUp) {
|
|
2856
2997
|
this.unreadMessageCount = 0;
|
|
2857
2998
|
}
|
|
2858
|
-
if (this.scrollContainer.nativeElement.scrollTop
|
|
2999
|
+
if (this.scrollContainer.nativeElement.scrollTop <=
|
|
3000
|
+
(((_a = this.parentMessageElement) === null || _a === void 0 ? void 0 : _a.nativeElement.clientHeight) || 0) &&
|
|
3001
|
+
(this.prevScrollTop === undefined ||
|
|
3002
|
+
this.prevScrollTop >
|
|
3003
|
+
(((_b = this.parentMessageElement) === null || _b === void 0 ? void 0 : _b.nativeElement.clientHeight) || 0))) {
|
|
2859
3004
|
this.containerHeight = this.scrollContainer.nativeElement.scrollHeight;
|
|
2860
|
-
|
|
3005
|
+
this.mode === 'main'
|
|
3006
|
+
? void this.channelService.loadMoreMessages()
|
|
3007
|
+
: void this.channelService.loadMoreThreadReplies();
|
|
2861
3008
|
}
|
|
3009
|
+
this.prevScrollTop = this.scrollContainer.nativeElement.scrollTop;
|
|
2862
3010
|
}
|
|
2863
3011
|
preserveScrollbarPosition() {
|
|
2864
3012
|
this.scrollContainer.nativeElement.scrollTop =
|
|
2865
|
-
this.
|
|
3013
|
+
(this.prevScrollTop || 0) +
|
|
3014
|
+
(this.scrollContainer.nativeElement.scrollHeight - this.containerHeight);
|
|
2866
3015
|
}
|
|
2867
3016
|
setEnabledActions() {
|
|
2868
3017
|
this.enabledMessageActions = [];
|
|
@@ -2874,6 +3023,7 @@ class MessageListComponent {
|
|
|
2874
3023
|
...this.enabledMessageActionsInput,
|
|
2875
3024
|
'send-reaction',
|
|
2876
3025
|
'read-events',
|
|
3026
|
+
'send-reply',
|
|
2877
3027
|
];
|
|
2878
3028
|
this.enabledMessageActionsInput.forEach((action) => {
|
|
2879
3029
|
const isAuthorized = this.authorizedMessageActions.indexOf(action) !== -1;
|
|
@@ -2882,9 +3032,61 @@ class MessageListComponent {
|
|
|
2882
3032
|
}
|
|
2883
3033
|
});
|
|
2884
3034
|
}
|
|
3035
|
+
setMessages$() {
|
|
3036
|
+
this.messages$ = (this.mode === 'main'
|
|
3037
|
+
? this.channelService.activeChannelMessages$
|
|
3038
|
+
: this.channelService.activeThreadMessages$).pipe(tap((messages) => {
|
|
3039
|
+
var _a, _b, _c, _d, _e;
|
|
3040
|
+
if (messages.length === 0) {
|
|
3041
|
+
return;
|
|
3042
|
+
}
|
|
3043
|
+
const currentLatestMessageDate = messages[messages.length - 1].created_at;
|
|
3044
|
+
if (!this.latestMessageDate ||
|
|
3045
|
+
((_a = this.latestMessageDate) === null || _a === void 0 ? void 0 : _a.getTime()) < currentLatestMessageDate.getTime()) {
|
|
3046
|
+
this.latestMessageDate = currentLatestMessageDate;
|
|
3047
|
+
this.hasNewMessages = true;
|
|
3048
|
+
this.isNewMessageSentByUser =
|
|
3049
|
+
((_b = messages[messages.length - 1].user) === null || _b === void 0 ? void 0 : _b.id) ===
|
|
3050
|
+
((_d = (_c = this.chatClientService.chatClient) === null || _c === void 0 ? void 0 : _c.user) === null || _d === void 0 ? void 0 : _d.id);
|
|
3051
|
+
if (this.isUserScrolledUp) {
|
|
3052
|
+
this.unreadMessageCount++;
|
|
3053
|
+
}
|
|
3054
|
+
}
|
|
3055
|
+
const currentOldestMessageDate = messages[0].created_at;
|
|
3056
|
+
if (!this.oldestMessageDate) {
|
|
3057
|
+
this.oldestMessageDate = currentOldestMessageDate;
|
|
3058
|
+
}
|
|
3059
|
+
else if (((_e = this.oldestMessageDate) === null || _e === void 0 ? void 0 : _e.getTime()) > currentOldestMessageDate.getTime()) {
|
|
3060
|
+
this.oldestMessageDate = currentOldestMessageDate;
|
|
3061
|
+
this.olderMassagesLoaded = true;
|
|
3062
|
+
}
|
|
3063
|
+
}), tap((messages) => {
|
|
3064
|
+
this.groupStyles = messages.map((m, i) => getGroupStyles(m, messages[i - 1], messages[i + 1]));
|
|
3065
|
+
}), tap((messages) => {
|
|
3066
|
+
var _a;
|
|
3067
|
+
return (this.lastSentMessageId = (_a = [...messages]
|
|
3068
|
+
.reverse()
|
|
3069
|
+
.find((m) => {
|
|
3070
|
+
var _a, _b, _c;
|
|
3071
|
+
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) &&
|
|
3072
|
+
m.status !== 'sending';
|
|
3073
|
+
})) === null || _a === void 0 ? void 0 : _a.id);
|
|
3074
|
+
}));
|
|
3075
|
+
}
|
|
3076
|
+
resetScrollState() {
|
|
3077
|
+
this.latestMessageDate = undefined;
|
|
3078
|
+
this.hasNewMessages = true;
|
|
3079
|
+
this.isUserScrolledUp = false;
|
|
3080
|
+
this.containerHeight = undefined;
|
|
3081
|
+
this.olderMassagesLoaded = false;
|
|
3082
|
+
this.oldestMessageDate = undefined;
|
|
3083
|
+
this.unreadMessageCount = 0;
|
|
3084
|
+
this.prevScrollTop = undefined;
|
|
3085
|
+
this.isNewMessageSentByUser = undefined;
|
|
3086
|
+
}
|
|
2885
3087
|
}
|
|
2886
3088
|
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
|
|
3089
|
+
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: i10.TranslateDirective, selector: "[translate],[ngx-translate]", inputs: ["translate", "translateParams"] }, { type: i6.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }], pipes: { "async": i6.AsyncPipe } });
|
|
2888
3090
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: MessageListComponent, decorators: [{
|
|
2889
3091
|
type: Component,
|
|
2890
3092
|
args: [{
|
|
@@ -2903,12 +3105,49 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImpor
|
|
|
2903
3105
|
}], enabledMessageActionsInput: [{
|
|
2904
3106
|
type: Input,
|
|
2905
3107
|
args: ['enabledMessageActions']
|
|
3108
|
+
}], mode: [{
|
|
3109
|
+
type: Input
|
|
2906
3110
|
}], class: [{
|
|
2907
3111
|
type: HostBinding,
|
|
2908
3112
|
args: ['class']
|
|
2909
3113
|
}], scrollContainer: [{
|
|
2910
3114
|
type: ViewChild,
|
|
2911
3115
|
args: ['scrollContainer']
|
|
3116
|
+
}], parentMessageElement: [{
|
|
3117
|
+
type: ViewChild,
|
|
3118
|
+
args: ['parentMessageElement']
|
|
3119
|
+
}] } });
|
|
3120
|
+
|
|
3121
|
+
class ThreadComponent {
|
|
3122
|
+
constructor(channelService) {
|
|
3123
|
+
this.channelService = channelService;
|
|
3124
|
+
this.class = 'str-chat__thread';
|
|
3125
|
+
this.subscriptions = [];
|
|
3126
|
+
this.subscriptions.push(this.channelService.activeParentMessage$.subscribe((parentMessage) => (this.parentMessage = parentMessage)));
|
|
3127
|
+
}
|
|
3128
|
+
ngOnDestroy() {
|
|
3129
|
+
this.subscriptions.forEach((s) => s.unsubscribe());
|
|
3130
|
+
}
|
|
3131
|
+
get replyCountParam() {
|
|
3132
|
+
var _a;
|
|
3133
|
+
return { replyCount: (_a = this.parentMessage) === null || _a === void 0 ? void 0 : _a.reply_count };
|
|
3134
|
+
}
|
|
3135
|
+
closeThread() {
|
|
3136
|
+
void this.channelService.setAsActiveParentMessage(undefined);
|
|
3137
|
+
}
|
|
3138
|
+
}
|
|
3139
|
+
ThreadComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: ThreadComponent, deps: [{ token: ChannelService }], target: i0.ɵɵFactoryTarget.Component });
|
|
3140
|
+
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: i10.TranslateDirective, selector: "[translate],[ngx-translate]", inputs: ["translate", "translateParams"] }], pipes: { "translate": i10.TranslatePipe } });
|
|
3141
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: ThreadComponent, decorators: [{
|
|
3142
|
+
type: Component,
|
|
3143
|
+
args: [{
|
|
3144
|
+
selector: 'stream-thread',
|
|
3145
|
+
templateUrl: './thread.component.html',
|
|
3146
|
+
styles: [],
|
|
3147
|
+
}]
|
|
3148
|
+
}], ctorParameters: function () { return [{ type: ChannelService }]; }, propDecorators: { class: [{
|
|
3149
|
+
type: HostBinding,
|
|
3150
|
+
args: ['class']
|
|
2912
3151
|
}] } });
|
|
2913
3152
|
|
|
2914
3153
|
class StreamAvatarModule {
|
|
@@ -2944,7 +3183,8 @@ StreamChatModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "12.0.0", versio
|
|
|
2944
3183
|
NotificationListComponent,
|
|
2945
3184
|
AttachmentPreviewListComponent,
|
|
2946
3185
|
ModalComponent,
|
|
2947
|
-
TextareaDirective
|
|
3186
|
+
TextareaDirective,
|
|
3187
|
+
ThreadComponent], imports: [CommonModule, TranslateModule, StreamAvatarModule], exports: [ChannelComponent,
|
|
2948
3188
|
ChannelHeaderComponent,
|
|
2949
3189
|
ChannelListComponent,
|
|
2950
3190
|
ChannelPreviewComponent,
|
|
@@ -2960,7 +3200,8 @@ StreamChatModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "12.0.0", versio
|
|
|
2960
3200
|
NotificationListComponent,
|
|
2961
3201
|
AttachmentPreviewListComponent,
|
|
2962
3202
|
ModalComponent,
|
|
2963
|
-
StreamAvatarModule
|
|
3203
|
+
StreamAvatarModule,
|
|
3204
|
+
ThreadComponent] });
|
|
2964
3205
|
StreamChatModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: StreamChatModule, imports: [[CommonModule, TranslateModule, StreamAvatarModule], StreamAvatarModule] });
|
|
2965
3206
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: StreamChatModule, decorators: [{
|
|
2966
3207
|
type: NgModule,
|
|
@@ -2983,6 +3224,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImpor
|
|
|
2983
3224
|
AttachmentPreviewListComponent,
|
|
2984
3225
|
ModalComponent,
|
|
2985
3226
|
TextareaDirective,
|
|
3227
|
+
ThreadComponent,
|
|
2986
3228
|
],
|
|
2987
3229
|
imports: [CommonModule, TranslateModule, StreamAvatarModule],
|
|
2988
3230
|
exports: [
|
|
@@ -3003,6 +3245,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImpor
|
|
|
3003
3245
|
AttachmentPreviewListComponent,
|
|
3004
3246
|
ModalComponent,
|
|
3005
3247
|
StreamAvatarModule,
|
|
3248
|
+
ThreadComponent,
|
|
3006
3249
|
],
|
|
3007
3250
|
}]
|
|
3008
3251
|
}] });
|
|
@@ -3065,5 +3308,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImpor
|
|
|
3065
3308
|
* Generated bundle index. Do not edit.
|
|
3066
3309
|
*/
|
|
3067
3310
|
|
|
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 };
|
|
3311
|
+
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
3312
|
//# sourceMappingURL=stream-chat-angular.js.map
|