stream-chat-angular 2.8.1 → 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 +618 -218
- package/bundles/stream-chat-angular.umd.js.map +1 -1
- package/esm2015/assets/i18n/en.js +3 -1
- package/esm2015/assets/version.js +2 -2
- package/esm2015/lib/attachment-list/attachment-list.component.js +21 -8
- package/esm2015/lib/channel/channel.component.js +3 -2
- package/esm2015/lib/channel.service.js +179 -38
- package/esm2015/lib/chat-client.service.js +6 -1
- package/esm2015/lib/icon/icon.component.js +2 -2
- package/esm2015/lib/message/message.component.js +18 -3
- package/esm2015/lib/message-actions-box/message-actions-box.component.js +15 -7
- package/esm2015/lib/message-input/autocomplete-textarea/autocomplete-textarea.component.js +35 -9
- package/esm2015/lib/message-input/message-input-config.service.js +1 -1
- package/esm2015/lib/message-input/message-input.component.js +40 -8
- package/esm2015/lib/message-input/textarea.directive.js +10 -2
- package/esm2015/lib/message-input/textarea.interface.js +1 -1
- package/esm2015/lib/message-list/message-list.component.js +126 -55
- 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/lib/types.js +1 -1
- package/esm2015/public-api.js +2 -1
- package/fesm2015/stream-chat-angular.js +491 -134
- package/fesm2015/stream-chat-angular.js.map +1 -1
- package/lib/attachment-list/attachment-list.component.d.ts +8 -3
- package/lib/channel/channel.component.d.ts +2 -1
- package/lib/channel.service.d.ts +20 -7
- package/lib/chat-client.service.d.ts +4 -3
- package/lib/icon/icon.component.d.ts +1 -1
- package/lib/message/message.component.d.ts +17 -3
- package/lib/message-actions-box/message-actions-box.component.d.ts +4 -1
- package/lib/message-input/autocomplete-textarea/autocomplete-textarea.component.d.ts +6 -3
- package/lib/message-input/message-input-config.service.d.ts +2 -1
- package/lib/message-input/message-input.component.d.ts +6 -2
- package/lib/message-input/textarea.directive.d.ts +3 -2
- package/lib/message-input/textarea.interface.d.ts +2 -1
- package/lib/message-list/message-list.component.d.ts +21 -7
- package/lib/message-preview.d.ts +1 -1
- package/lib/stream-chat.module.d.ts +5 -4
- package/lib/thread/thread.component.d.ts +18 -0
- package/lib/types.d.ts +7 -1
- package/package.json +2 -2
- package/public-api.d.ts +1 -0
- package/src/assets/i18n/en.ts +4 -0
- package/src/assets/version.ts +1 -1
|
@@ -1,13 +1,13 @@
|
|
|
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';
|
|
10
|
-
import * as
|
|
10
|
+
import * as i6 from '@angular/common';
|
|
11
11
|
import { CommonModule } from '@angular/common';
|
|
12
12
|
import Dayjs from 'dayjs';
|
|
13
13
|
import calendar from 'dayjs/plugin/calendar';
|
|
@@ -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() {
|
|
@@ -105,6 +105,11 @@ class ChatClientService {
|
|
|
105
105
|
});
|
|
106
106
|
});
|
|
107
107
|
}
|
|
108
|
+
disconnectUser() {
|
|
109
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
110
|
+
yield this.chatClient.disconnectUser();
|
|
111
|
+
});
|
|
112
|
+
}
|
|
108
113
|
getAppSettings() {
|
|
109
114
|
return __awaiter(this, void 0, void 0, function* () {
|
|
110
115
|
if (this.appSettingsSubject.getValue()) {
|
|
@@ -144,7 +149,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImpor
|
|
|
144
149
|
}]
|
|
145
150
|
}], ctorParameters: function () { return [{ type: i0.NgZone }, { type: NotificationService }]; } });
|
|
146
151
|
|
|
147
|
-
const createMessagePreview = (user, text, attachments, mentionedUsers) => {
|
|
152
|
+
const createMessagePreview = (user, text, attachments, mentionedUsers, parentId) => {
|
|
148
153
|
const clientSideId = `${user.id}-${v4()}`;
|
|
149
154
|
return {
|
|
150
155
|
__html: text,
|
|
@@ -158,6 +163,7 @@ const createMessagePreview = (user, text, attachments, mentionedUsers) => {
|
|
|
158
163
|
user,
|
|
159
164
|
attachments,
|
|
160
165
|
mentioned_users: mentionedUsers,
|
|
166
|
+
parent_id: parentId,
|
|
161
167
|
};
|
|
162
168
|
};
|
|
163
169
|
|
|
@@ -183,31 +189,50 @@ class ChannelService {
|
|
|
183
189
|
this.activeChannelMessagesSubject = new BehaviorSubject([]);
|
|
184
190
|
this.hasMoreChannelsSubject = new ReplaySubject(1);
|
|
185
191
|
this.activeChannelSubscriptions = [];
|
|
192
|
+
this.activeParentMessageIdSubject = new BehaviorSubject(undefined);
|
|
193
|
+
this.activeThreadMessagesSubject = new BehaviorSubject([]);
|
|
194
|
+
this.messagePageSize = 25;
|
|
186
195
|
this.channelListSetter = (channels) => {
|
|
187
196
|
this.channelsSubject.next(channels);
|
|
188
197
|
};
|
|
189
198
|
this.messageListSetter = (messages) => {
|
|
190
199
|
this.activeChannelMessagesSubject.next(messages);
|
|
191
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
|
+
};
|
|
192
207
|
this.channels$ = this.channelsSubject.asObservable();
|
|
193
208
|
this.activeChannel$ = this.activeChannelSubject.asObservable();
|
|
194
209
|
this.activeChannelMessages$ = this.activeChannelMessagesSubject.pipe(map((messages) => {
|
|
195
210
|
const channel = this.activeChannelSubject.getValue();
|
|
196
|
-
return messages.map((message) =>
|
|
197
|
-
if (this.isStreamMessage(message) &&
|
|
198
|
-
this.isFormatMessageResponse(message)) {
|
|
199
|
-
return message;
|
|
200
|
-
}
|
|
201
|
-
else if (this.isFormatMessageResponse(message)) {
|
|
202
|
-
return Object.assign(Object.assign({}, message), { readBy: getReadBy(message, channel) });
|
|
203
|
-
}
|
|
204
|
-
else {
|
|
205
|
-
const formatMessage = this.formatMessage(message);
|
|
206
|
-
return Object.assign(Object.assign({}, formatMessage), { readBy: getReadBy(formatMessage, channel) });
|
|
207
|
-
}
|
|
208
|
-
});
|
|
211
|
+
return messages.map((message) => this.transformToStreamMessage(message, channel));
|
|
209
212
|
}));
|
|
210
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
|
+
});
|
|
211
236
|
}
|
|
212
237
|
setAsActiveChannel(channel) {
|
|
213
238
|
const prevActiveChannel = this.activeChannelSubject.getValue();
|
|
@@ -221,25 +246,61 @@ class ChannelService {
|
|
|
221
246
|
void channel.markRead();
|
|
222
247
|
}
|
|
223
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
|
+
});
|
|
224
268
|
}
|
|
269
|
+
// load more thread replies
|
|
225
270
|
loadMoreMessages() {
|
|
226
|
-
var _a, _b, _c, _d;
|
|
271
|
+
var _a, _b, _c, _d, _e;
|
|
227
272
|
return __awaiter(this, void 0, void 0, function* () {
|
|
228
273
|
const activeChnannel = this.activeChannelSubject.getValue();
|
|
229
274
|
const lastMessageId = (_a = this.activeChannelMessagesSubject.getValue()[0]) === null || _a === void 0 ? void 0 : _a.id;
|
|
230
275
|
yield (activeChnannel === null || activeChnannel === void 0 ? void 0 : activeChnannel.query({
|
|
231
|
-
messages: { limit:
|
|
276
|
+
messages: { limit: (_b = this.options) === null || _b === void 0 ? void 0 : _b.message_limit, id_lt: lastMessageId },
|
|
232
277
|
members: { limit: 0 },
|
|
233
278
|
watchers: { limit: 0 },
|
|
234
279
|
}));
|
|
235
|
-
if (((
|
|
236
|
-
((
|
|
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)) {
|
|
237
282
|
this.activeChannelMessagesSubject.next([
|
|
238
283
|
...activeChnannel.state.messages,
|
|
239
284
|
]);
|
|
240
285
|
}
|
|
241
286
|
});
|
|
242
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
|
+
}
|
|
243
304
|
init(filters, sort, options) {
|
|
244
305
|
return __awaiter(this, void 0, void 0, function* () {
|
|
245
306
|
this.filters = filters;
|
|
@@ -249,13 +310,20 @@ class ChannelService {
|
|
|
249
310
|
state: true,
|
|
250
311
|
presence: true,
|
|
251
312
|
watch: true,
|
|
252
|
-
message_limit:
|
|
313
|
+
message_limit: this.messagePageSize,
|
|
253
314
|
};
|
|
254
315
|
this.sort = sort || { last_message_at: -1, updated_at: -1 };
|
|
255
316
|
yield this.queryChannels();
|
|
256
317
|
this.chatClientService.notification$.subscribe((notification) => void this.handleNotification(notification));
|
|
257
318
|
});
|
|
258
319
|
}
|
|
320
|
+
reset() {
|
|
321
|
+
this.activeChannelMessagesSubject.next([]);
|
|
322
|
+
this.activeChannelSubject.next(undefined);
|
|
323
|
+
this.activeParentMessageIdSubject.next(undefined);
|
|
324
|
+
this.activeThreadMessagesSubject.next([]);
|
|
325
|
+
this.channelsSubject.next(undefined);
|
|
326
|
+
}
|
|
259
327
|
loadMoreChannels() {
|
|
260
328
|
return __awaiter(this, void 0, void 0, function* () {
|
|
261
329
|
this.options.offset = this.channels.length;
|
|
@@ -277,9 +345,9 @@ class ChannelService {
|
|
|
277
345
|
.getValue()) === null || _a === void 0 ? void 0 : _a.deleteReaction(messageId, reactionType));
|
|
278
346
|
});
|
|
279
347
|
}
|
|
280
|
-
sendMessage(text, attachments = [], mentionedUsers = []) {
|
|
348
|
+
sendMessage(text, attachments = [], mentionedUsers = [], parentId = undefined) {
|
|
281
349
|
return __awaiter(this, void 0, void 0, function* () {
|
|
282
|
-
const preview = createMessagePreview(this.chatClientService.chatClient.user, text, attachments, mentionedUsers);
|
|
350
|
+
const preview = createMessagePreview(this.chatClientService.chatClient.user, text, attachments, mentionedUsers, parentId);
|
|
283
351
|
const channel = this.activeChannelSubject.getValue();
|
|
284
352
|
preview.readBy = [];
|
|
285
353
|
channel.state.addMessageSorted(preview, true);
|
|
@@ -357,18 +425,60 @@ class ChannelService {
|
|
|
357
425
|
}
|
|
358
426
|
});
|
|
359
427
|
}
|
|
428
|
+
sendAction(messageId, formData) {
|
|
429
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
430
|
+
const channel = this.activeChannelSubject.getValue();
|
|
431
|
+
const response = yield channel.sendAction(messageId, formData);
|
|
432
|
+
if (response === null || response === void 0 ? void 0 : response.message) {
|
|
433
|
+
channel.state.addMessageSorted(Object.assign(Object.assign({}, response.message), { status: 'received' }));
|
|
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]);
|
|
440
|
+
}
|
|
441
|
+
else {
|
|
442
|
+
channel.state.removeMessage({ id: messageId });
|
|
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
|
+
}
|
|
453
|
+
}
|
|
454
|
+
});
|
|
455
|
+
}
|
|
360
456
|
sendMessageRequest(preview) {
|
|
361
457
|
var _a;
|
|
362
458
|
return __awaiter(this, void 0, void 0, function* () {
|
|
363
459
|
const channel = this.activeChannelSubject.getValue();
|
|
364
|
-
|
|
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]);
|
|
365
466
|
try {
|
|
366
|
-
yield channel.sendMessage({
|
|
467
|
+
const response = yield channel.sendMessage({
|
|
367
468
|
text: preview.text,
|
|
368
469
|
attachments: preview.attachments,
|
|
369
470
|
mentioned_users: (_a = preview.mentioned_users) === null || _a === void 0 ? void 0 : _a.map((u) => u.id),
|
|
370
471
|
id: preview.id,
|
|
472
|
+
parent_id: preview.parent_id,
|
|
371
473
|
});
|
|
474
|
+
if (response === null || response === void 0 ? void 0 : response.message) {
|
|
475
|
+
channel.state.addMessageSorted(Object.assign(Object.assign({}, response.message), { status: 'received' }), true);
|
|
476
|
+
isThreadReply
|
|
477
|
+
? this.activeThreadMessagesSubject.next([
|
|
478
|
+
...channel.state.threads[preview.parent_id],
|
|
479
|
+
])
|
|
480
|
+
: this.activeChannelMessagesSubject.next([...channel.state.messages]);
|
|
481
|
+
}
|
|
372
482
|
}
|
|
373
483
|
catch (error) {
|
|
374
484
|
const stringError = JSON.stringify(error);
|
|
@@ -376,7 +486,11 @@ class ChannelService {
|
|
|
376
486
|
? JSON.parse(stringError)
|
|
377
487
|
: {};
|
|
378
488
|
channel.state.addMessageSorted(Object.assign(Object.assign({}, preview), { errorStatusCode: parsedError.status || undefined, status: 'failed' }), true);
|
|
379
|
-
|
|
489
|
+
isThreadReply
|
|
490
|
+
? this.activeThreadMessagesSubject.next([
|
|
491
|
+
...channel.state.threads[preview.parent_id],
|
|
492
|
+
])
|
|
493
|
+
: this.activeChannelMessagesSubject.next([...channel.state.messages]);
|
|
380
494
|
}
|
|
381
495
|
});
|
|
382
496
|
}
|
|
@@ -454,9 +568,15 @@ class ChannelService {
|
|
|
454
568
|
}
|
|
455
569
|
}
|
|
456
570
|
watchForActiveChannelEvents(channel) {
|
|
457
|
-
this.activeChannelSubscriptions.push(channel.on('message.new', () => {
|
|
571
|
+
this.activeChannelSubscriptions.push(channel.on('message.new', (event) => {
|
|
458
572
|
this.ngZone.run(() => {
|
|
459
|
-
|
|
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
|
+
]);
|
|
460
580
|
this.activeChannel$.pipe(first()).subscribe((c) => {
|
|
461
581
|
if (this.canSendReadEvents) {
|
|
462
582
|
void (c === null || c === void 0 ? void 0 : c.markRead());
|
|
@@ -485,19 +605,27 @@ class ChannelService {
|
|
|
485
605
|
}
|
|
486
606
|
messageUpdated(event) {
|
|
487
607
|
this.ngZone.run(() => {
|
|
488
|
-
const
|
|
608
|
+
const isThreadReply = event.message && event.message.parent_id;
|
|
609
|
+
const messages = isThreadReply
|
|
610
|
+
? this.activeThreadMessagesSubject.getValue()
|
|
611
|
+
: this.activeChannelMessagesSubject.getValue();
|
|
489
612
|
const messageIndex = messages.findIndex((m) => { var _a; return m.id === ((_a = event.message) === null || _a === void 0 ? void 0 : _a.id); });
|
|
490
613
|
if (messageIndex !== -1 && event.message) {
|
|
491
614
|
messages[messageIndex] = event.message;
|
|
492
|
-
|
|
615
|
+
isThreadReply
|
|
616
|
+
? this.activeThreadMessagesSubject.next([...messages])
|
|
617
|
+
: this.activeChannelMessagesSubject.next([...messages]);
|
|
493
618
|
}
|
|
494
619
|
});
|
|
495
620
|
}
|
|
496
621
|
messageReactionEventReceived(e) {
|
|
497
622
|
this.ngZone.run(() => {
|
|
498
623
|
var _a, _b, _c, _d;
|
|
624
|
+
const isThreadMessage = e.message && e.message.parent_id;
|
|
499
625
|
let messages;
|
|
500
|
-
|
|
626
|
+
(isThreadMessage
|
|
627
|
+
? this.activeThreadMessages$
|
|
628
|
+
: this.activeChannelMessages$)
|
|
501
629
|
.pipe(first())
|
|
502
630
|
.subscribe((m) => (messages = m));
|
|
503
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); });
|
|
@@ -508,7 +636,9 @@ class ChannelService {
|
|
|
508
636
|
message.reaction_scores = Object.assign({}, (_b = e.message) === null || _b === void 0 ? void 0 : _b.reaction_scores);
|
|
509
637
|
message.latest_reactions = [...(((_c = e.message) === null || _c === void 0 ? void 0 : _c.latest_reactions) || [])];
|
|
510
638
|
message.own_reactions = [...(((_d = e.message) === null || _d === void 0 ? void 0 : _d.own_reactions) || [])];
|
|
511
|
-
|
|
639
|
+
isThreadMessage
|
|
640
|
+
? this.activeThreadMessagesSubject.next([...messages])
|
|
641
|
+
: this.activeChannelMessagesSubject.next([...messages]);
|
|
512
642
|
});
|
|
513
643
|
}
|
|
514
644
|
formatMessage(message) {
|
|
@@ -556,7 +686,7 @@ class ChannelService {
|
|
|
556
686
|
case 'message.new': {
|
|
557
687
|
this.ngZone.run(() => {
|
|
558
688
|
if (this.customNewMessageHandler) {
|
|
559
|
-
this.customNewMessageHandler(event, channel, this.channelListSetter, this.messageListSetter);
|
|
689
|
+
this.customNewMessageHandler(event, channel, this.channelListSetter, this.messageListSetter, this.threadListSetter, this.parentMessageSetter);
|
|
560
690
|
}
|
|
561
691
|
else {
|
|
562
692
|
this.handleNewMessage(event, channel);
|
|
@@ -567,7 +697,7 @@ class ChannelService {
|
|
|
567
697
|
case 'channel.hidden': {
|
|
568
698
|
this.ngZone.run(() => {
|
|
569
699
|
if (this.customChannelHiddenHandler) {
|
|
570
|
-
this.customChannelHiddenHandler(event, channel, this.channelListSetter, this.messageListSetter);
|
|
700
|
+
this.customChannelHiddenHandler(event, channel, this.channelListSetter, this.messageListSetter, this.threadListSetter, this.parentMessageSetter);
|
|
571
701
|
}
|
|
572
702
|
else {
|
|
573
703
|
this.handleChannelHidden(event);
|
|
@@ -578,7 +708,7 @@ class ChannelService {
|
|
|
578
708
|
case 'channel.deleted': {
|
|
579
709
|
this.ngZone.run(() => {
|
|
580
710
|
if (this.customChannelDeletedHandler) {
|
|
581
|
-
this.customChannelDeletedHandler(event, channel, this.channelListSetter, this.messageListSetter);
|
|
711
|
+
this.customChannelDeletedHandler(event, channel, this.channelListSetter, this.messageListSetter, this.threadListSetter, this.parentMessageSetter);
|
|
582
712
|
}
|
|
583
713
|
else {
|
|
584
714
|
this.handleChannelDeleted(event);
|
|
@@ -589,7 +719,7 @@ class ChannelService {
|
|
|
589
719
|
case 'channel.visible': {
|
|
590
720
|
this.ngZone.run(() => {
|
|
591
721
|
if (this.customChannelVisibleHandler) {
|
|
592
|
-
this.customChannelVisibleHandler(event, channel, this.channelListSetter, this.messageListSetter);
|
|
722
|
+
this.customChannelVisibleHandler(event, channel, this.channelListSetter, this.messageListSetter, this.threadListSetter, this.parentMessageSetter);
|
|
593
723
|
}
|
|
594
724
|
else {
|
|
595
725
|
this.handleChannelVisible(event, channel);
|
|
@@ -600,7 +730,7 @@ class ChannelService {
|
|
|
600
730
|
case 'channel.updated': {
|
|
601
731
|
this.ngZone.run(() => {
|
|
602
732
|
if (this.customChannelUpdatedHandler) {
|
|
603
|
-
this.customChannelUpdatedHandler(event, channel, this.channelListSetter, this.messageListSetter);
|
|
733
|
+
this.customChannelUpdatedHandler(event, channel, this.channelListSetter, this.messageListSetter, this.threadListSetter, this.parentMessageSetter);
|
|
604
734
|
}
|
|
605
735
|
else {
|
|
606
736
|
this.handleChannelUpdate(event);
|
|
@@ -611,7 +741,7 @@ class ChannelService {
|
|
|
611
741
|
case 'channel.truncated': {
|
|
612
742
|
this.ngZone.run(() => {
|
|
613
743
|
if (this.customChannelTruncatedHandler) {
|
|
614
|
-
this.customChannelTruncatedHandler(event, channel, this.channelListSetter, this.messageListSetter);
|
|
744
|
+
this.customChannelTruncatedHandler(event, channel, this.channelListSetter, this.messageListSetter, this.threadListSetter, this.parentMessageSetter);
|
|
615
745
|
}
|
|
616
746
|
else {
|
|
617
747
|
this.handleChannelTruncate(event);
|
|
@@ -651,6 +781,7 @@ class ChannelService {
|
|
|
651
781
|
}
|
|
652
782
|
}
|
|
653
783
|
}
|
|
784
|
+
// truncate active thread as well
|
|
654
785
|
handleChannelTruncate(event) {
|
|
655
786
|
var _a, _b;
|
|
656
787
|
const channelIndex = this.channels.findIndex((c) => c.cid === event.channel.cid);
|
|
@@ -662,6 +793,8 @@ class ChannelService {
|
|
|
662
793
|
channel.state.messages = [];
|
|
663
794
|
this.activeChannelSubject.next(channel);
|
|
664
795
|
this.activeChannelMessagesSubject.next([]);
|
|
796
|
+
this.activeParentMessageIdSubject.next(undefined);
|
|
797
|
+
this.activeThreadMessagesSubject.next([]);
|
|
665
798
|
}
|
|
666
799
|
}
|
|
667
800
|
}
|
|
@@ -677,6 +810,20 @@ class ChannelService {
|
|
|
677
810
|
const capabilites = (_a = channel.data) === null || _a === void 0 ? void 0 : _a.own_capabilities;
|
|
678
811
|
return capabilites.indexOf('read-events') !== -1;
|
|
679
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
|
+
}
|
|
680
827
|
}
|
|
681
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 });
|
|
682
829
|
ChannelService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: ChannelService, providedIn: 'root' });
|
|
@@ -989,6 +1136,7 @@ const en = {
|
|
|
989
1136
|
Flag: 'Flag',
|
|
990
1137
|
'Message Failed': 'Message Failed',
|
|
991
1138
|
'Message Failed · Unauthorized': 'Message Failed · Unauthorized',
|
|
1139
|
+
'Message Failed · Click to try again': 'Message Failed · Click to try again',
|
|
992
1140
|
'Message deleted': 'Message deleted',
|
|
993
1141
|
'Message has been successfully flagged': 'Message has been successfully flagged',
|
|
994
1142
|
'Message pinned': 'Message pinned',
|
|
@@ -1039,6 +1187,7 @@ const en = {
|
|
|
1039
1187
|
test: 'success',
|
|
1040
1188
|
'Sending links is not allowed in this conversation': 'Sending links is not allowed in this conversation',
|
|
1041
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",
|
|
1042
1191
|
'Unsupported file type: {{type}}': 'Unsupported file type: {{type}}',
|
|
1043
1192
|
},
|
|
1044
1193
|
};
|
|
@@ -1075,7 +1224,7 @@ class AvatarComponent {
|
|
|
1075
1224
|
}
|
|
1076
1225
|
}
|
|
1077
1226
|
AvatarComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: AvatarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1078
|
-
AvatarComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.5", type: AvatarComponent, selector: "stream-avatar", inputs: { name: "name", imageUrl: "imageUrl", size: "size" }, ngImport: i0, template: "<div\n class=\"str-chat__avatar str-chat__avatar--circle\"\n title=\"{{ name }}\"\n [style]=\"{\n flexBasis: size + 'px',\n fontSize: size / 2 + 'px',\n height: size + 'px',\n lineHeight: size + 'px',\n width: size + 'px'\n }\"\n>\n <img\n *ngIf=\"imageUrl && !isError; else fallback\"\n class=\"str-chat__avatar-image str-chat__avatar-image{{\n isLoaded ? ' str-chat__avatar-image--loaded' : ''\n }}\"\n src=\"{{ imageUrl }}\"\n alt=\"{{ initials }}\"\n data-testid=\"avatar-img\"\n (load)=\"isLoaded = true\"\n (error)=\"isError = true\"\n [style]=\"{\n flexBasis: size + 'px',\n height: size + 'px',\n objectFit: 'cover',\n width: size + 'px'\n }\"\n />\n <ng-template #fallback>\n <div data-testid=\"fallback-img\" class=\"str-chat__avatar-fallback\">\n {{ initials }}\n </div>\n </ng-template>\n</div>\n", styles: [""], directives: [{ type:
|
|
1227
|
+
AvatarComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.5", type: AvatarComponent, selector: "stream-avatar", inputs: { name: "name", imageUrl: "imageUrl", size: "size" }, ngImport: i0, template: "<div\n class=\"str-chat__avatar str-chat__avatar--circle\"\n title=\"{{ name }}\"\n [style]=\"{\n flexBasis: size + 'px',\n fontSize: size / 2 + 'px',\n height: size + 'px',\n lineHeight: size + 'px',\n width: size + 'px'\n }\"\n>\n <img\n *ngIf=\"imageUrl && !isError; else fallback\"\n class=\"str-chat__avatar-image str-chat__avatar-image{{\n isLoaded ? ' str-chat__avatar-image--loaded' : ''\n }}\"\n src=\"{{ imageUrl }}\"\n alt=\"{{ initials }}\"\n data-testid=\"avatar-img\"\n (load)=\"isLoaded = true\"\n (error)=\"isError = true\"\n [style]=\"{\n flexBasis: size + 'px',\n height: size + 'px',\n objectFit: 'cover',\n width: size + 'px'\n }\"\n />\n <ng-template #fallback>\n <div data-testid=\"fallback-img\" class=\"str-chat__avatar-fallback\">\n {{ initials }}\n </div>\n </ng-template>\n</div>\n", styles: [""], directives: [{ type: i6.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }] });
|
|
1079
1228
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: AvatarComponent, decorators: [{
|
|
1080
1229
|
type: Component,
|
|
1081
1230
|
args: [{
|
|
@@ -1095,7 +1244,7 @@ class IconComponent {
|
|
|
1095
1244
|
constructor() { }
|
|
1096
1245
|
}
|
|
1097
1246
|
IconComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: IconComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1098
|
-
IconComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.5", type: IconComponent, selector: "stream-icon", inputs: { icon: "icon", size: "size" }, ngImport: i0, template: "<svg\n data-testid=\"action-icon\"\n *ngIf=\"icon === 'action-icon'\"\n height=\"4\"\n viewBox=\"0 0 11 4\"\n width=\"11\"\n xmlns=\"http://www.w3.org/2000/svg\"\n>\n <path\n d=\"M1.5 3a1.5 1.5 0 1 1 0-3 1.5 1.5 0 0 1 0 3zm4 0a1.5 1.5 0 1 1 0-3 1.5 1.5 0 0 1 0 3zm4 0a1.5 1.5 0 1 1 0-3 1.5 1.5 0 0 1 0 3z\"\n fillRule=\"nonzero\"\n />\n</svg>\n<svg\n *ngIf=\"icon === 'delivered-icon'\"\n height=\"16\"\n width=\"16\"\n xmlns=\"http://www.w3.org/2000/svg\"\n data-testid=\"delivered-icon\"\n>\n <path\n d=\"M8 0a8 8 0 1 1 0 16A8 8 0 0 1 8 0zm3.72 6.633a.955.955 0 1 0-1.352-1.352L6.986 8.663 5.633 7.31A.956.956 0 1 0 4.28 8.663l2.029 2.028a.956.956 0 0 0 1.353 0l4.058-4.058z\"\n fill=\"#006CFF\"\n fillRule=\"evenodd\"\n />\n</svg>\n<svg\n *ngIf=\"icon === 'reaction-icon'\"\n height=\"12\"\n viewBox=\"0 0 12 12\"\n width=\"12\"\n xmlns=\"http://www.w3.org/2000/svg\"\n data-testid=\"reaction-icon\"\n>\n <g clipRule=\"evenodd\" fillRule=\"evenodd\">\n <path\n d=\"M6 1.2C3.3 1.2 1.2 3.3 1.2 6c0 2.7 2.1 4.8 4.8 4.8 2.7 0 4.8-2.1 4.8-4.8 0-2.7-2.1-4.8-4.8-4.8zM0 6c0-3.3 2.7-6 6-6s6 2.7 6 6-2.7 6-6 6-6-2.7-6-6z\"\n ></path>\n <path\n d=\"M5.4 4.5c0 .5-.4.9-.9.9s-.9-.4-.9-.9.4-.9.9-.9.9.4.9.9zM8.4 4.5c0 .5-.4.9-.9.9s-.9-.4-.9-.9.4-.9.9-.9.9.4.9.9zM3.3 6.7c.3-.2.6-.1.8.1.3.4.8.9 1.5 1 .6.2 1.4.1 2.4-1 .2-.2.6-.3.8 0 .2.2.3.6 0 .8-1.1 1.3-2.4 1.7-3.5 1.5-1-.2-1.8-.9-2.2-1.5-.2-.3-.1-.7.2-.9z\"\n ></path>\n </g>\n</svg>\n<svg\n data-testid=\"connection-error\"\n *ngIf=\"icon === 'connection-error'\"\n width=\"78px\"\n height=\"78px\"\n viewBox=\"0 0 78 78\"\n version=\"1.1\"\n xmlns=\"http://www.w3.org/2000/svg\"\n xmlns:xlink=\"http://www.w3.org/1999/xlink\"\n>\n <!-- Generator: Sketch 52.6 (67491) - http://www.bohemiancoding.com/sketch -->\n <title>Combined Shape</title>\n <desc>Created with Sketch.</desc>\n <g\n id=\"Interactions\"\n stroke=\"none\"\n stroke-width=\"1\"\n fill=\"none\"\n fill-rule=\"evenodd\"\n >\n <g\n id=\"Connection-Error-_-Connectivity\"\n transform=\"translate(-270.000000, -30.000000)\"\n fill=\"#CF1F25\"\n >\n <g\n id=\"109-network-connection\"\n transform=\"translate(270.000000, 30.000000)\"\n >\n <path\n d=\"M66.4609744,11.414231 C81.6225232,26.5757798 81.6225232,51.157545 66.4609744,66.3188467 C51.2994256,81.4803954 26.7176604,81.4803954 11.5563587,66.3188467 C-3.60519004,51.1572979 -3.60519004,26.5755327 11.5563587,11.414231 C26.7179075,-3.74731776 51.2996727,-3.74731776 66.4609744,11.414231 Z M54.7853215,45.8823776 L54.7853215,40.5882574 C54.7853215,39.613638 53.9952341,38.8235506 53.0206147,38.8235506 L44.9576695,38.8235506 L41.428256,42.3529641 L51.255555,42.3529641 L51.255555,45.8823776 L54.7853215,45.8823776 Z M40.6659027,43.1153174 L37.8988425,45.8823776 L40.6659027,45.8823776 L40.6659027,43.1153174 Z M51.1764962,56.4702653 L58.2353232,56.4702653 C59.2099355,56.4702653 60.00003,55.6801708 60.00003,54.7055585 L60.00003,51.176145 C60.00003,50.2015327 59.2099355,49.4114382 58.2353232,49.4114382 L51.1764962,49.4114382 C50.2018839,49.4114382 49.4117894,50.2015327 49.4117894,51.176145 L49.4117894,54.7055585 C49.4117894,55.6801708 50.2018839,56.4702653 51.1764962,56.4702653 Z M35.2941353,56.4702653 L42.3529624,56.4702653 C43.3275746,56.4702653 44.1176691,55.6801708 44.1176691,54.7055585 L44.1176691,51.176145 C44.1176691,50.2015327 43.3275746,49.4114382 42.3529624,49.4114382 L35.2941353,49.4114382 C34.319523,49.4114382 33.5294285,50.2015327 33.5294285,51.176145 L33.5294285,54.7055585 C33.5294285,55.6801708 34.319523,56.4702653 35.2941353,56.4702653 Z M56.6964989,19.0874231 C56.007381,18.3985134 54.8903216,18.3985134 54.2012036,19.087423 L45.882376,27.4062507 L45.882376,19.4117761 C45.882376,18.4371568 45.0922885,17.6470693 44.1176692,17.6470693 L33.5294286,17.6470693 C32.5548092,17.6470694 31.7647218,18.4371568 31.7647218,19.4117761 L31.7647218,30.0000167 C31.7647219,30.9746363 32.5548092,31.7647237 33.5294285,31.7647237 L41.5239031,31.7647237 L34.4650761,38.8235508 L24.7058947,38.8235508 C23.7312753,38.8235508 22.9411879,39.6136382 22.9411879,40.5882575 L22.9411879,45.8823778 L26.4706014,45.8823778 L26.4706014,42.3529643 L30.9356624,42.3529643 L23.8768354,49.4117914 L19.4117743,49.4117914 C18.4371549,49.4117914 17.6470675,50.2018788 17.6470675,51.1764981 L17.6470675,54.7059117 C17.6504049,54.9674302 17.7129076,55.2248042 17.8298886,55.4587302 L16.4456526,56.8429662 C15.7446193,57.5200453 15.7252005,58.6372282 16.4022825,59.3382615 C17.0793616,60.0392948 18.1965445,60.0587136 18.8975778,59.3816316 C18.9122847,59.3674273 18.9267436,59.3529684 18.940948,59.3382615 L56.6964963,21.5830662 C57.3856425,20.8939094 57.3856425,19.7765747 56.6964963,19.0874179 Z\"\n id=\"Combined-Shape\"\n ></path>\n </g>\n </g>\n </g>\n</svg>\n<svg\n *ngIf=\"icon === 'send'\"\n data-testid=\"send\"\n height=\"17\"\n viewBox=\"0 0 18 17\"\n width=\"18\"\n xmlns=\"http://www.w3.org/2000/svg\"\n>\n <title translate>streamChat.Send</title>\n <path\n d=\"M0 17.015l17.333-8.508L0 0v6.617l12.417 1.89L0 10.397z\"\n fill=\"#006cff\"\n fillRule=\"evenodd\"\n />\n</svg>\n<svg\n *ngIf=\"icon === 'file-upload'\"\n data-testid=\"file-upload\"\n height=\"14\"\n width=\"14\"\n xmlns=\"http://www.w3.org/2000/svg\"\n>\n <title translate>streamChat.Attach files</title>\n <path\n d=\"M1.667.333h10.666c.737 0 1.334.597 1.334 1.334v10.666c0 .737-.597 1.334-1.334 1.334H1.667a1.333 1.333 0 0 1-1.334-1.334V1.667C.333.93.93.333 1.667.333zm2 1.334a1.667 1.667 0 1 0 0 3.333 1.667 1.667 0 0 0 0-3.333zm-2 9.333v1.333h10.666v-4l-2-2-4 4-2-2L1.667 11z\"\n fillRule=\"nonzero\"\n />\n</svg>\n<svg\n data-testid=\"retry\"\n *ngIf=\"icon === 'retry'\"\n width=\"22\"\n height=\"20\"\n viewBox=\"0 0 22 20\"\n xmlns=\"http://www.w3.org/2000/svg\"\n>\n <path\n d=\"M20 5.535V2a1 1 0 0 1 2 0v6a1 1 0 0 1-1 1h-6a1 1 0 0 1 0-2h3.638l-2.975-2.653a8 8 0 1 0 1.884 8.32 1 1 0 1 1 1.886.666A10 10 0 1 1 5.175 1.245c3.901-2.15 8.754-1.462 11.88 1.667L20 5.535z\"\n fill=\"#FFF\"\n fill-rule=\"nonzero\"\n />\n</svg>\n<svg\n *ngIf=\"icon === 'close'\"\n data-testid=\"close\"\n width=\"28\"\n height=\"28\"\n viewBox=\"0 0 28 28\"\n xmlns=\"http://www.w3.org/2000/svg\"\n xmlns:xlink=\"http://www.w3.org/1999/xlink\"\n>\n <defs>\n <path\n d=\"M465 5c5.53 0 10 4.47 10 10s-4.47 10-10 10-10-4.47-10-10 4.47-10 10-10zm3.59 5L465 13.59 461.41 10 460 11.41l3.59 3.59-3.59 3.59 1.41 1.41 3.59-3.59 3.59 3.59 1.41-1.41-3.59-3.59 3.59-3.59-1.41-1.41z\"\n id=\"b\"\n />\n <filter\n x=\"-30%\"\n y=\"-30%\"\n width=\"160%\"\n height=\"160%\"\n filterUnits=\"objectBoundingBox\"\n id=\"a\"\n >\n <feOffset in=\"SourceAlpha\" result=\"shadowOffsetOuter1\" />\n <feGaussianBlur\n stdDeviation=\"2\"\n in=\"shadowOffsetOuter1\"\n result=\"shadowBlurOuter1\"\n />\n <feColorMatrix\n values=\"0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.5 0\"\n in=\"shadowBlurOuter1\"\n />\n </filter>\n </defs>\n <g transform=\"translate(-451 -1)\" fill-rule=\"nonzero\" fill=\"none\">\n <use fill=\"#000\" filter=\"url(#a)\" xlink:href=\"#b\" />\n <use fill=\"#FFF\" fill-rule=\"evenodd\" xlink:href=\"#b\" />\n </g>\n</svg>\n<svg\n *ngIf=\"icon === 'file'\"\n data-testid=\"file\"\n className=\"rfu-file-icon--small fa-file-fallback\"\n [attr.height]=\"size || 20\"\n [attr.width]=\"size || 20\"\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 384 512\"\n>\n <path\n d=\"M369.9 97.9L286 14C277 5 264.8-.1 252.1-.1H48C21.5 0 0 21.5 0 48v416c0 26.5 21.5 48 48 48h288c26.5 0 48-21.5 48-48V131.9c0-12.7-5.1-25-14.1-34zM332.1 128H256V51.9l76.1 76.1zM48 464V48h160v104c0 13.3 10.7 24 24 24h104v288H48z\"\n fill=\"#414D54\"\n />\n</svg>\n", directives: [{ type:
|
|
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"] }] });
|
|
1099
1248
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: IconComponent, decorators: [{
|
|
1100
1249
|
type: Component,
|
|
1101
1250
|
args: [{
|
|
@@ -1116,7 +1265,7 @@ class LoadingIndicatorComponent {
|
|
|
1116
1265
|
}
|
|
1117
1266
|
}
|
|
1118
1267
|
LoadingIndicatorComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: LoadingIndicatorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1119
|
-
LoadingIndicatorComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.5", type: LoadingIndicatorComponent, selector: "stream-loading-indicator", inputs: { size: "size", color: "color" }, ngImport: i0, template: "<div class=\"str-chat__loading-indicator\">\n <svg\n [attr.height]=\"size\"\n viewBox=\"0 0 30 30\"\n [attr.width]=\"size\"\n data-testid=\"loading-indicator\"\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <defs>\n <linearGradient id=\"a\" x1=\"50%\" x2=\"50%\" y1=\"0%\" y2=\"100%\">\n <stop offset=\"0%\" stop-color=\"#FFF\" stop-opacity=\"0\" />\n <stop\n data-testid=\"stop-color\"\n offset=\"100%\"\n [attr.stop-color]=\"color\"\n stop-opacity=\"1\"\n [ngStyle]=\"{ stopColor: color }\"\n />\n </linearGradient>\n </defs>\n <path\n d=\"M2.518 23.321l1.664-1.11A12.988 12.988 0 0 0 15 28c7.18 0 13-5.82 13-13S22.18 2 15 2V0c8.284 0 15 6.716 15 15 0 8.284-6.716 15-15 15-5.206 0-9.792-2.652-12.482-6.679z\"\n fill=\"url(#a)\"\n fillRule=\"evenodd\"\n />\n </svg>\n</div>\n", directives: [{ type:
|
|
1268
|
+
LoadingIndicatorComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.5", type: LoadingIndicatorComponent, selector: "stream-loading-indicator", inputs: { size: "size", color: "color" }, ngImport: i0, template: "<div class=\"str-chat__loading-indicator\">\n <svg\n [attr.height]=\"size\"\n viewBox=\"0 0 30 30\"\n [attr.width]=\"size\"\n data-testid=\"loading-indicator\"\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <defs>\n <linearGradient id=\"a\" x1=\"50%\" x2=\"50%\" y1=\"0%\" y2=\"100%\">\n <stop offset=\"0%\" stop-color=\"#FFF\" stop-opacity=\"0\" />\n <stop\n data-testid=\"stop-color\"\n offset=\"100%\"\n [attr.stop-color]=\"color\"\n stop-opacity=\"1\"\n [ngStyle]=\"{ stopColor: color }\"\n />\n </linearGradient>\n </defs>\n <path\n d=\"M2.518 23.321l1.664-1.11A12.988 12.988 0 0 0 15 28c7.18 0 13-5.82 13-13S22.18 2 15 2V0c8.284 0 15 6.716 15 15 0 8.284-6.716 15-15 15-5.206 0-9.792-2.652-12.482-6.679z\"\n fill=\"url(#a)\"\n fillRule=\"evenodd\"\n />\n </svg>\n</div>\n", directives: [{ type: i6.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }] });
|
|
1120
1269
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: LoadingIndicatorComponent, decorators: [{
|
|
1121
1270
|
type: Component,
|
|
1122
1271
|
args: [{
|
|
@@ -1158,6 +1307,8 @@ class TextareaDirective {
|
|
|
1158
1307
|
this.componentRef.instance.areMentionsEnabled = this.areMentionsEnabled;
|
|
1159
1308
|
this.componentRef.instance.mentionAutocompleteItemTemplate =
|
|
1160
1309
|
this.mentionAutocompleteItemTemplate;
|
|
1310
|
+
this.componentRef.instance.commandAutocompleteItemTemplate =
|
|
1311
|
+
this.commandAutocompleteItemTemplate;
|
|
1161
1312
|
this.componentRef.instance.mentionScope = this.mentionScope;
|
|
1162
1313
|
this.componentRef.instance.value = this.value;
|
|
1163
1314
|
}
|
|
@@ -1169,6 +1320,10 @@ class TextareaDirective {
|
|
|
1169
1320
|
this.componentRef.instance.mentionAutocompleteItemTemplate =
|
|
1170
1321
|
this.mentionAutocompleteItemTemplate;
|
|
1171
1322
|
}
|
|
1323
|
+
if (changes.commandAutocompleteItemTemplate) {
|
|
1324
|
+
this.componentRef.instance.commandAutocompleteItemTemplate =
|
|
1325
|
+
this.commandAutocompleteItemTemplate;
|
|
1326
|
+
}
|
|
1172
1327
|
if (changes.mentionScope) {
|
|
1173
1328
|
this.componentRef.instance.mentionScope = this.mentionScope;
|
|
1174
1329
|
}
|
|
@@ -1184,7 +1339,7 @@ class TextareaDirective {
|
|
|
1184
1339
|
}
|
|
1185
1340
|
}
|
|
1186
1341
|
TextareaDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: TextareaDirective, deps: [{ token: i0.ViewContainerRef }], target: i0.ɵɵFactoryTarget.Directive });
|
|
1187
|
-
TextareaDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "12.2.5", type: TextareaDirective, selector: "[streamTextarea]", inputs: { componentRef: "componentRef", areMentionsEnabled: "areMentionsEnabled", mentionAutocompleteItemTemplate: "mentionAutocompleteItemTemplate", mentionScope: "mentionScope", value: "value" }, outputs: { valueChange: "valueChange", send: "send", userMentions: "userMentions" }, usesOnChanges: true, ngImport: i0 });
|
|
1342
|
+
TextareaDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "12.2.5", type: TextareaDirective, selector: "[streamTextarea]", inputs: { componentRef: "componentRef", areMentionsEnabled: "areMentionsEnabled", mentionAutocompleteItemTemplate: "mentionAutocompleteItemTemplate", mentionScope: "mentionScope", commandAutocompleteItemTemplate: "commandAutocompleteItemTemplate", value: "value" }, outputs: { valueChange: "valueChange", send: "send", userMentions: "userMentions" }, usesOnChanges: true, ngImport: i0 });
|
|
1188
1343
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: TextareaDirective, decorators: [{
|
|
1189
1344
|
type: Directive,
|
|
1190
1345
|
args: [{
|
|
@@ -1198,6 +1353,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImpor
|
|
|
1198
1353
|
type: Input
|
|
1199
1354
|
}], mentionScope: [{
|
|
1200
1355
|
type: Input
|
|
1356
|
+
}], commandAutocompleteItemTemplate: [{
|
|
1357
|
+
type: Input
|
|
1201
1358
|
}], value: [{
|
|
1202
1359
|
type: Input
|
|
1203
1360
|
}], valueChange: [{
|
|
@@ -1245,7 +1402,7 @@ class AttachmentPreviewListComponent {
|
|
|
1245
1402
|
}
|
|
1246
1403
|
}
|
|
1247
1404
|
AttachmentPreviewListComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: AttachmentPreviewListComponent, deps: [{ token: AttachmentService }], target: i0.ɵɵFactoryTarget.Component });
|
|
1248
|
-
AttachmentPreviewListComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.5", type: AttachmentPreviewListComponent, selector: "stream-attachment-preview-list", ngImport: i0, template: "<div class=\"rfu-image-previewer\" *ngIf=\"(attachmentUploads$ | async)?.length\">\n <ng-container\n *ngFor=\"\n let attachmentUpload of attachmentUploads$ | async;\n trackBy: trackByFile\n \"\n >\n <div\n *ngIf=\"attachmentUpload.type === 'image'\"\n class=\"rfu-image-previewer__image\"\n [class.rfu-image-previewer__image--loaded]=\"\n attachmentUpload.state === 'success'\n \"\n data-testclass=\"attachment-image-preview\"\n >\n <div\n *ngIf=\"attachmentUpload.state === 'error'\"\n class=\"rfu-image-previewer__retry\"\n (click)=\"retryAttachmentUpload(attachmentUpload.file)\"\n (keyup.enter)=\"retryAttachmentUpload(attachmentUpload.file)\"\n data-testclass=\"upload-error\"\n >\n <stream-icon icon=\"retry\"></stream-icon>\n </div>\n <div class=\"rfu-thumbnail__wrapper\" style=\"width: 100; height: 100\">\n <div class=\"rfu-thumbnail__overlay\">\n <div\n class=\"rfu-icon-button\"\n data-testclass=\"delete-attachment\"\n role=\"button\"\n (click)=\"deleteAttachment(attachmentUpload)\"\n (keyup.enter)=\"deleteAttachment(attachmentUpload)\"\n >\n <stream-icon icon=\"close\"></stream-icon>\n </div>\n </div>\n <img\n *ngIf=\"attachmentUpload.url || attachmentUpload.previewUri\"\n src=\"{{\n attachmentUpload.url\n ? attachmentUpload.url\n : attachmentUpload.previewUri\n }}\"\n alt=\"attachmentUpload.file.name\"\n class=\"rfu-thumbnail__image\"\n data-testclass=\"attachment-image\"\n />\n </div>\n <stream-loading-indicator\n data-testclass=\"loading-indicator\"\n color=\"rgba(255,255,255,0.7)\"\n *ngIf=\"attachmentUpload.state === 'uploading'\"\n ></stream-loading-indicator>\n </div>\n <div\n class=\"rfu-file-previewer\"\n *ngIf=\"attachmentUpload.type === 'file'\"\n data-testclass=\"attachment-file-preview\"\n >\n <ol>\n <li\n class=\"rfu-file-previewer__file\"\n [class.rfu-file-previewer__file--uploading]=\"\n attachmentUpload.state === 'uploading'\n \"\n [class.rfu-file-previewer__file--failed]=\"\n attachmentUpload.state === 'error'\n \"\n >\n <stream-icon icon=\"file\"></stream-icon>\n\n <a\n data-testclass=\"file-download-link\"\n href=\"{{ attachmentUpload.url }}\"\n (click)=\"attachmentUpload.url ? null : $event.preventDefault()\"\n (keyup.enter)=\"\n attachmentUpload.url ? null : $event.preventDefault()\n \"\n download\n >\n {{ attachmentUpload.file.name }}\n <ng-container *ngIf=\"attachmentUpload.state === 'error'\">\n <div\n data-testclass=\"file-upload-retry\"\n class=\"rfu-file-previewer__failed\"\n (click)=\"retryAttachmentUpload(attachmentUpload.file)\"\n (keyup.enter)=\"retryAttachmentUpload(attachmentUpload.file)\"\n translate\n >\n streamChat.failed\n </div>\n <div\n class=\"rfu-file-previewer__retry\"\n (click)=\"retryAttachmentUpload(attachmentUpload.file)\"\n (keyup.enter)=\"retryAttachmentUpload(attachmentUpload.file)\"\n translate\n >\n streamChat.retry\n </div>\n </ng-container>\n </a>\n\n <span\n data-testclass=\"file-delete\"\n class=\"rfu-file-previewer__close-button\"\n (click)=\"deleteAttachment(attachmentUpload)\"\n (keyup.enter)=\"deleteAttachment(attachmentUpload)\"\n >\n \u2718\n </span>\n <div\n *ngIf=\"attachmentUpload.state === 'uploading'\"\n class=\"rfu-file-previewer__loading-indicator\"\n >\n <stream-loading-indicator></stream-loading-indicator>\n </div>\n </li>\n </ol>\n </div>\n </ng-container>\n</div>\n", components: [{ type: IconComponent, selector: "stream-icon", inputs: ["icon", "size"] }, { type: LoadingIndicatorComponent, selector: "stream-loading-indicator", inputs: ["size", "color"] }], directives: [{ type:
|
|
1405
|
+
AttachmentPreviewListComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.5", type: AttachmentPreviewListComponent, selector: "stream-attachment-preview-list", ngImport: i0, template: "<div class=\"rfu-image-previewer\" *ngIf=\"(attachmentUploads$ | async)?.length\">\n <ng-container\n *ngFor=\"\n let attachmentUpload of attachmentUploads$ | async;\n trackBy: trackByFile\n \"\n >\n <div\n *ngIf=\"attachmentUpload.type === 'image'\"\n class=\"rfu-image-previewer__image\"\n [class.rfu-image-previewer__image--loaded]=\"\n attachmentUpload.state === 'success'\n \"\n data-testclass=\"attachment-image-preview\"\n >\n <div\n *ngIf=\"attachmentUpload.state === 'error'\"\n class=\"rfu-image-previewer__retry\"\n (click)=\"retryAttachmentUpload(attachmentUpload.file)\"\n (keyup.enter)=\"retryAttachmentUpload(attachmentUpload.file)\"\n data-testclass=\"upload-error\"\n >\n <stream-icon icon=\"retry\"></stream-icon>\n </div>\n <div class=\"rfu-thumbnail__wrapper\" style=\"width: 100; height: 100\">\n <div class=\"rfu-thumbnail__overlay\">\n <div\n class=\"rfu-icon-button\"\n data-testclass=\"delete-attachment\"\n role=\"button\"\n (click)=\"deleteAttachment(attachmentUpload)\"\n (keyup.enter)=\"deleteAttachment(attachmentUpload)\"\n >\n <stream-icon icon=\"close\"></stream-icon>\n </div>\n </div>\n <img\n *ngIf=\"attachmentUpload.url || attachmentUpload.previewUri\"\n src=\"{{\n attachmentUpload.url\n ? attachmentUpload.url\n : attachmentUpload.previewUri\n }}\"\n alt=\"attachmentUpload.file.name\"\n class=\"rfu-thumbnail__image\"\n data-testclass=\"attachment-image\"\n />\n </div>\n <stream-loading-indicator\n data-testclass=\"loading-indicator\"\n color=\"rgba(255,255,255,0.7)\"\n *ngIf=\"attachmentUpload.state === 'uploading'\"\n ></stream-loading-indicator>\n </div>\n <div\n class=\"rfu-file-previewer\"\n *ngIf=\"attachmentUpload.type === 'file'\"\n data-testclass=\"attachment-file-preview\"\n >\n <ol>\n <li\n class=\"rfu-file-previewer__file\"\n [class.rfu-file-previewer__file--uploading]=\"\n attachmentUpload.state === 'uploading'\n \"\n [class.rfu-file-previewer__file--failed]=\"\n attachmentUpload.state === 'error'\n \"\n >\n <stream-icon icon=\"file\"></stream-icon>\n\n <a\n data-testclass=\"file-download-link\"\n href=\"{{ attachmentUpload.url }}\"\n (click)=\"attachmentUpload.url ? null : $event.preventDefault()\"\n (keyup.enter)=\"\n attachmentUpload.url ? null : $event.preventDefault()\n \"\n download\n >\n {{ attachmentUpload.file.name }}\n <ng-container *ngIf=\"attachmentUpload.state === 'error'\">\n <div\n data-testclass=\"file-upload-retry\"\n class=\"rfu-file-previewer__failed\"\n (click)=\"retryAttachmentUpload(attachmentUpload.file)\"\n (keyup.enter)=\"retryAttachmentUpload(attachmentUpload.file)\"\n translate\n >\n streamChat.failed\n </div>\n <div\n class=\"rfu-file-previewer__retry\"\n (click)=\"retryAttachmentUpload(attachmentUpload.file)\"\n (keyup.enter)=\"retryAttachmentUpload(attachmentUpload.file)\"\n translate\n >\n streamChat.retry\n </div>\n </ng-container>\n </a>\n\n <span\n data-testclass=\"file-delete\"\n class=\"rfu-file-previewer__close-button\"\n (click)=\"deleteAttachment(attachmentUpload)\"\n (keyup.enter)=\"deleteAttachment(attachmentUpload)\"\n >\n \u2718\n </span>\n <div\n *ngIf=\"attachmentUpload.state === 'uploading'\"\n class=\"rfu-file-previewer__loading-indicator\"\n >\n <stream-loading-indicator></stream-loading-indicator>\n </div>\n </li>\n </ol>\n </div>\n </ng-container>\n</div>\n", components: [{ type: IconComponent, selector: "stream-icon", inputs: ["icon", "size"] }, { type: LoadingIndicatorComponent, selector: "stream-loading-indicator", inputs: ["size", "color"] }], directives: [{ type: i6.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i6.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i10.TranslateDirective, selector: "[translate],[ngx-translate]", inputs: ["translate", "translateParams"] }], pipes: { "async": i6.AsyncPipe } });
|
|
1249
1406
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: AttachmentPreviewListComponent, decorators: [{
|
|
1250
1407
|
type: Component,
|
|
1251
1408
|
args: [{
|
|
@@ -1265,6 +1422,7 @@ class MessageInputComponent {
|
|
|
1265
1422
|
this.componentFactoryResolver = componentFactoryResolver;
|
|
1266
1423
|
this.cdRef = cdRef;
|
|
1267
1424
|
this.chatClient = chatClient;
|
|
1425
|
+
this.mode = 'main';
|
|
1268
1426
|
this.messageUpdate = new EventEmitter();
|
|
1269
1427
|
this.textareaValue = '';
|
|
1270
1428
|
this.mentionedUsers = [];
|
|
@@ -1285,11 +1443,8 @@ class MessageInputComponent {
|
|
|
1285
1443
|
this.isFileUploadAuthorized =
|
|
1286
1444
|
capabilities.indexOf('upload-file') !== -1;
|
|
1287
1445
|
this.canSendLinks = capabilities.indexOf('send-links') !== -1;
|
|
1288
|
-
this.
|
|
1289
|
-
|
|
1290
|
-
this.cdRef.detectChanges();
|
|
1291
|
-
this.initTextarea();
|
|
1292
|
-
}
|
|
1446
|
+
this.channel = channel;
|
|
1447
|
+
this.setCanSendMessages();
|
|
1293
1448
|
}
|
|
1294
1449
|
}));
|
|
1295
1450
|
this.subscriptions.push(this.chatClient.appSettings$.subscribe((appSettings) => (this.appSettings = appSettings)));
|
|
@@ -1302,6 +1457,8 @@ class MessageInputComponent {
|
|
|
1302
1457
|
this.mentionAutocompleteItemTemplate =
|
|
1303
1458
|
this.configService.mentionAutocompleteItemTemplate;
|
|
1304
1459
|
this.mentionScope = this.configService.mentionScope;
|
|
1460
|
+
this.commandAutocompleteItemTemplate =
|
|
1461
|
+
this.configService.commandAutocompleteItemTemplate;
|
|
1305
1462
|
}
|
|
1306
1463
|
ngAfterViewInit() {
|
|
1307
1464
|
this.isViewInited = true;
|
|
@@ -1332,9 +1489,16 @@ class MessageInputComponent {
|
|
|
1332
1489
|
this.configService.mentionAutocompleteItemTemplate =
|
|
1333
1490
|
this.mentionAutocompleteItemTemplate;
|
|
1334
1491
|
}
|
|
1492
|
+
if (changes.commandAutocompleteItemTemplate) {
|
|
1493
|
+
this.configService.commandAutocompleteItemTemplate =
|
|
1494
|
+
this.commandAutocompleteItemTemplate;
|
|
1495
|
+
}
|
|
1335
1496
|
if (changes.mentionScope) {
|
|
1336
1497
|
this.configService.mentionScope = this.mentionScope;
|
|
1337
1498
|
}
|
|
1499
|
+
if (changes.mode) {
|
|
1500
|
+
this.setCanSendMessages();
|
|
1501
|
+
}
|
|
1338
1502
|
}
|
|
1339
1503
|
ngOnDestroy() {
|
|
1340
1504
|
this.subscriptions.forEach((s) => s.unsubscribe());
|
|
@@ -1364,10 +1528,16 @@ class MessageInputComponent {
|
|
|
1364
1528
|
if (!this.isUpdate) {
|
|
1365
1529
|
this.textareaValue = '';
|
|
1366
1530
|
}
|
|
1531
|
+
let parentMessageId = undefined;
|
|
1532
|
+
if (this.mode === 'thread') {
|
|
1533
|
+
this.channelService.activeParentMessageId$
|
|
1534
|
+
.pipe(first())
|
|
1535
|
+
.subscribe((id) => (parentMessageId = id));
|
|
1536
|
+
}
|
|
1367
1537
|
try {
|
|
1368
1538
|
yield (this.isUpdate
|
|
1369
1539
|
? this.channelService.updateMessage(Object.assign(Object.assign({}, this.message), { text: text, attachments: attachments }))
|
|
1370
|
-
: this.channelService.sendMessage(text, attachments, this.mentionedUsers));
|
|
1540
|
+
: this.channelService.sendMessage(text, attachments, this.mentionedUsers, parentMessageId));
|
|
1371
1541
|
this.messageUpdate.emit();
|
|
1372
1542
|
if (!this.isUpdate) {
|
|
1373
1543
|
this.attachmentService.resetAttachmentUploads();
|
|
@@ -1461,9 +1631,24 @@ class MessageInputComponent {
|
|
|
1461
1631
|
return isValid;
|
|
1462
1632
|
});
|
|
1463
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
|
+
}
|
|
1464
1649
|
}
|
|
1465
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 });
|
|
1466
|
-
MessageInputComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.5", type: MessageInputComponent, selector: "stream-message-input", inputs: { isFileUploadEnabled: "isFileUploadEnabled", areMentionsEnabled: "areMentionsEnabled", mentionScope: "mentionScope", mentionAutocompleteItemTemplate: "mentionAutocompleteItemTemplate", acceptedFileTypes: "acceptedFileTypes", isMultipleFileUploadEnabled: "isMultipleFileUploadEnabled", message: "message" }, outputs: { messageUpdate: "messageUpdate" }, providers: [AttachmentService], viewQueries: [{ propertyName: "fileInput", first: true, predicate: ["fileInput"], descendants: true }, { propertyName: "textareaAnchor", first: true, predicate: TextareaDirective, descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div\n class=\"str-chat__input-flat\"\n [class.str-chat__input-flat-has-attachments]=\"\n (attachmentUploads$ | async)!.length > 0\n \"\n>\n <div class=\"str-chat__input-flat-wrapper\">\n <div
|
|
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 } });
|
|
1467
1652
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: MessageInputComponent, decorators: [{
|
|
1468
1653
|
type: Component,
|
|
1469
1654
|
args: [{
|
|
@@ -1483,6 +1668,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImpor
|
|
|
1483
1668
|
type: Input
|
|
1484
1669
|
}], mentionAutocompleteItemTemplate: [{
|
|
1485
1670
|
type: Input
|
|
1671
|
+
}], commandAutocompleteItemTemplate: [{
|
|
1672
|
+
type: Input
|
|
1673
|
+
}], mode: [{
|
|
1674
|
+
type: Input
|
|
1486
1675
|
}], acceptedFileTypes: [{
|
|
1487
1676
|
type: Input
|
|
1488
1677
|
}], isMultipleFileUploadEnabled: [{
|
|
@@ -1584,7 +1773,7 @@ class NotificationListComponent {
|
|
|
1584
1773
|
}
|
|
1585
1774
|
}
|
|
1586
1775
|
NotificationListComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: NotificationListComponent, deps: [{ token: NotificationService }], target: i0.ɵɵFactoryTarget.Component });
|
|
1587
|
-
NotificationListComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.5", type: NotificationListComponent, selector: "stream-notification-list", ngImport: i0, template: "<div class=\"str-chat__list-notifications\">\n <stream-notification\n *ngFor=\"let notification of notifications$ | async; trackBy: trackByItem\"\n [type]=\"notification.type\"\n ><div data-testclass=\"notification-content\">\n {{ notification.text | translate: notification.translateParams }}\n </div></stream-notification\n >\n</div>\n", components: [{ type: NotificationComponent, selector: "stream-notification", inputs: ["type"] }], directives: [{ type:
|
|
1776
|
+
NotificationListComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.5", type: NotificationListComponent, selector: "stream-notification-list", ngImport: i0, template: "<div class=\"str-chat__list-notifications\">\n <stream-notification\n *ngFor=\"let notification of notifications$ | async; trackBy: trackByItem\"\n [type]=\"notification.type\"\n ><div data-testclass=\"notification-content\">\n {{ notification.text | translate: notification.translateParams }}\n </div></stream-notification\n >\n</div>\n", components: [{ type: NotificationComponent, selector: "stream-notification", inputs: ["type"] }], directives: [{ type: i6.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }], pipes: { "async": i6.AsyncPipe, "translate": i10.TranslatePipe } });
|
|
1588
1777
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: NotificationListComponent, decorators: [{
|
|
1589
1778
|
type: Component,
|
|
1590
1779
|
args: [{
|
|
@@ -1638,18 +1827,26 @@ class MessageActionsBoxComponent {
|
|
|
1638
1827
|
return this.enabledActions.indexOf('quote') !== -1;
|
|
1639
1828
|
}
|
|
1640
1829
|
get isEditVisible() {
|
|
1641
|
-
return ((this.enabledActions.indexOf('edit') !== -1
|
|
1642
|
-
this.enabledActions.indexOf('
|
|
1830
|
+
return (((this.enabledActions.indexOf('edit') !== -1 ||
|
|
1831
|
+
this.enabledActions.indexOf('update-own-message') !== -1) &&
|
|
1832
|
+
this.isMine) ||
|
|
1833
|
+
this.enabledActions.indexOf('edit-any') !== -1 ||
|
|
1834
|
+
this.enabledActions.indexOf('update-any-message') !== -1);
|
|
1643
1835
|
}
|
|
1644
1836
|
get isDeleteVisible() {
|
|
1645
|
-
return ((this.enabledActions.indexOf('delete') !== -1
|
|
1646
|
-
this.enabledActions.indexOf('delete-
|
|
1837
|
+
return (((this.enabledActions.indexOf('delete') !== -1 ||
|
|
1838
|
+
this.enabledActions.indexOf('delete-own-message') !== -1) &&
|
|
1839
|
+
this.isMine) ||
|
|
1840
|
+
this.enabledActions.indexOf('delete-any') !== -1 ||
|
|
1841
|
+
this.enabledActions.indexOf('delete-any-message') !== -1);
|
|
1647
1842
|
}
|
|
1648
1843
|
get isMuteVisible() {
|
|
1649
1844
|
return this.enabledActions.indexOf('mute') !== -1;
|
|
1650
1845
|
}
|
|
1651
1846
|
get isFlagVisible() {
|
|
1652
|
-
return this.enabledActions.indexOf('flag') !== -1
|
|
1847
|
+
return ((this.enabledActions.indexOf('flag') !== -1 ||
|
|
1848
|
+
this.enabledActions.indexOf('flag-message') !== -1) &&
|
|
1849
|
+
!this.isMine);
|
|
1653
1850
|
}
|
|
1654
1851
|
get isPinVisible() {
|
|
1655
1852
|
return this.enabledActions.indexOf('pin') !== -1;
|
|
@@ -1694,7 +1891,7 @@ class MessageActionsBoxComponent {
|
|
|
1694
1891
|
}
|
|
1695
1892
|
}
|
|
1696
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 });
|
|
1697
|
-
MessageActionsBoxComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.5", type: MessageActionsBoxComponent, selector: "stream-message-actions-box", inputs: { messageInputTemplate: "messageInputTemplate", isOpen: "isOpen", isMine: "isMine", message: "message", enabledActions: "enabledActions" }, outputs: { displayedActionsCount: "displayedActionsCount", isEditing: "isEditing" }, viewQueries: [{ propertyName: "messageInput", first: true, predicate: MessageInputComponent, descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div\n data-testid=\"action-box\"\n class=\"str-chat__message-actions-box\"\n [class.str-chat__message-actions-box--open]=\"isOpen\"\n [class.str-chat__message-actions-box--mine]=\"isMine\"\n>\n <ul class=\"str-chat__message-actions-list\">\n <button\n data-testid=\"quote-action\"\n *ngIf=\"isQuoteVisible\"\n (click)=\"quoteClicked()\"\n >\n <li class=\"str-chat__message-actions-list-item\">\n {{ \"streamChat.Reply\" | translate }}\n </li>\n </button>\n <button\n data-testid=\"pin-action\"\n *ngIf=\"isPinVisible\"\n (click)=\"pinClicked()\"\n >\n <li class=\"str-chat__message-actions-list-item\">\n {{\n (message?.pinned ? \"streamChat.Unpin\" : \"streamChat.Pin\") | translate\n }}\n </li>\n </button>\n <button\n data-testid=\"flag-action\"\n *ngIf=\"isFlagVisible\"\n (click)=\"flagClicked()\"\n >\n <li class=\"str-chat__message-actions-list-item\">\n {{ \"streamChat.Flag\" | translate }}\n </li>\n </button>\n <button\n data-testid=\"mute-action\"\n *ngIf=\"isMuteVisible\"\n (click)=\"muteClicked()\"\n >\n <li class=\"str-chat__message-actions-list-item\">\n {{ \"streamChat.Mute\" | translate }}\n </li>\n </button>\n <button\n data-testid=\"edit-action\"\n *ngIf=\"isEditVisible\"\n (click)=\"editClicked()\"\n >\n <li class=\"str-chat__message-actions-list-item\">\n {{ \"streamChat.Edit Message\" | translate }}\n </li>\n </button>\n <button\n data-testid=\"delete-action\"\n *ngIf=\"isDeleteVisible\"\n (click)=\"deleteClicked()\"\n >\n <li class=\"str-chat__message-actions-list-item\">\n {{ \"streamChat.Delete\" | translate }}\n </li>\n </button>\n </ul>\n</div>\n\n<stream-modal\n [isOpen]=\"isEditModalOpen\"\n (isOpenChange)=\"\n isEditModalOpen = $event; isEditModalOpen ? '' : modalClosed()\n \"\n>\n <div class=\"str-chat__edit-message-form\" *ngIf=\"isEditModalOpen\">\n <ng-container *ngIf=\"messageInputTemplate; else defaultInput\">\n <ng-container\n *ngTemplateOutlet=\"\n messageInputTemplate;\n context: {\n message: message,\n messageUpdateHandler: modalClosed\n }\n \"\n ></ng-container>\n </ng-container>\n <ng-template #defaultInput>\n <stream-message-input\n [message]=\"message\"\n (messageUpdate)=\"modalClosed()\"\n ></stream-message-input>\n </ng-template>\n <stream-notification-list></stream-notification-list>\n <div\n class=\"\n str-chat__message-team-form-footer\n str-chat__message-team-form-footer-angular\n \"\n >\n <div class=\"str-chat__edit-message-form-options\">\n <button translate data-testid=\"cancel-button\" (click)=\"modalClosed()\">\n streamChat.Cancel\n </button>\n <button\n type=\"submit\"\n translate\n data-testid=\"send-button\"\n (click)=\"sendClicked()\"\n (keyup.enter)=\"sendClicked()\"\n >\n streamChat.Send\n </button>\n </div>\n </div>\n </div>\n</stream-modal>\n", components: [{ type: ModalComponent, selector: "stream-modal", inputs: ["isOpen"], outputs: ["isOpenChange"] }, { type: MessageInputComponent, selector: "stream-message-input", inputs: ["isFileUploadEnabled", "areMentionsEnabled", "mentionScope", "mentionAutocompleteItemTemplate", "acceptedFileTypes", "isMultipleFileUploadEnabled", "message"], outputs: ["messageUpdate"] }, { type: NotificationListComponent, selector: "stream-notification-list" }], directives: [{ type:
|
|
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 } });
|
|
1698
1895
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: MessageActionsBoxComponent, decorators: [{
|
|
1699
1896
|
type: Component,
|
|
1700
1897
|
args: [{
|
|
@@ -1727,10 +1924,11 @@ class ChannelComponent {
|
|
|
1727
1924
|
this.subscriptions = [];
|
|
1728
1925
|
this.isError$ = this.channelService.channels$.pipe(map(() => false), catchError(() => of(true)), startWith(false));
|
|
1729
1926
|
this.isInitializing$ = this.channelService.channels$.pipe(map((channels) => !channels), catchError(() => of(false)));
|
|
1927
|
+
this.isActiveThread$ = this.channelService.activeParentMessageId$.pipe(map((id) => !!id));
|
|
1730
1928
|
}
|
|
1731
1929
|
}
|
|
1732
1930
|
ChannelComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: ChannelComponent, deps: [{ token: ChannelService }], target: i0.ɵɵFactoryTarget.Component });
|
|
1733
|
-
ChannelComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.5", type: ChannelComponent, selector: "stream-channel", ngImport: i0, template: "<div\n *ngIf=\"(isError$ | async) === false && (isInitializing$ | async) === false\"\n class=\"str-chat str-chat-channel messaging\"\n>\n <div class=\"str-chat__container\">\n <div class=\"str-chat__main-panel\">\n <ng-content></ng-content>\n </div>\n </div>\n</div>\n", directives: [{ type:
|
|
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 } });
|
|
1734
1932
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: ChannelComponent, decorators: [{
|
|
1735
1933
|
type: Component,
|
|
1736
1934
|
args: [{
|
|
@@ -1956,7 +2154,7 @@ class ChannelListComponent {
|
|
|
1956
2154
|
}
|
|
1957
2155
|
}
|
|
1958
2156
|
ChannelListComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: ChannelListComponent, deps: [{ token: ChannelService }, { token: ChannelListToggleService }], target: i0.ɵɵFactoryTarget.Component });
|
|
1959
|
-
ChannelListComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.5", type: ChannelListComponent, selector: "stream-channel-list", inputs: { customChannelPreviewTemplate: "customChannelPreviewTemplate" }, viewQueries: [{ propertyName: "container", first: true, predicate: ["container"], descendants: true }], ngImport: i0, template: "<div\n #container\n data-testid=\"channel-list-container\"\n class=\"str-chat str-chat-channel-list messaging\"\n [class.str-chat-channel-list--open]=\"(isOpen$ | async) === true\"\n>\n <div\n *ngIf=\"\n (isError$ | async) === false && (isInitializing$ | async) === false;\n else statusIndicator\n \"\n class=\"str-chat__channel-list-messenger\"\n >\n <div class=\"str-chat__channel-list-messenger__main\">\n <p\n data-testid=\"empty-channel-list-indicator\"\n *ngIf=\"!(channels$ | async)?.length\"\n >\n {{ \"streamChat.You have no channels currently\" | translate }}\n </p>\n <ng-container\n *ngFor=\"let channel of channels$ | async; trackBy: trackByChannelId\"\n >\n <ng-container\n *ngIf=\"customChannelPreviewTemplate; else defaultTemplate\"\n >\n <div (click)=\"channelSelected()\" (keyup.enter)=\"channelSelected()\">\n <ng-container\n *ngTemplateOutlet=\"\n customChannelPreviewTemplate;\n context: { channel: channel }\n \"\n ></ng-container>\n </div>\n </ng-container>\n <ng-template #defaultTemplate>\n <stream-channel-preview\n data-testclass=\"channel-preview\"\n [channel]=\"channel\"\n (click)=\"channelSelected()\"\n (keyup.enter)=\"channelSelected()\"\n ></stream-channel-preview>\n </ng-template>\n </ng-container>\n <div\n *ngIf=\"hasMoreChannels$ | async\"\n class=\"str-chat__load-more-button\"\n (click)=\"loadMoreChannels()\"\n (keyup.enter)=\"loadMoreChannels()\"\n data-testid=\"load-more\"\n >\n <button\n class=\"str-chat__load-more-button__button\"\n data-testid=\"load-more-button\"\n [disabled]=\"isLoadingMoreChannels\"\n >\n <span *ngIf=\"!isLoadingMoreChannels; else loadingIndicator\">{{\n \"Load more\" | translate\n }}</span>\n <ng-template #loadingIndicator\n ><stream-loading-indicator></stream-loading-indicator\n ></ng-template>\n </button>\n </div>\n </div>\n </div>\n</div>\n\n<ng-template #statusIndicator>\n <ng-container *ngIf=\"isError$ | async\">\n <ng-container *ngTemplateOutlet=\"chatDown\"></ng-container>\n </ng-container>\n <ng-container *ngIf=\"isInitializing$ | async\">\n <ng-container *ngTemplateOutlet=\"loadingChannels\"></ng-container>\n </ng-container>\n</ng-template>\n\n<ng-template #chatDown>\n <div data-testid=\"chatdown-container\" class=\"str-chat__down\">\n <ng-container *ngTemplateOutlet=\"loadingChannels\"></ng-container>\n <div class=\"str-chat__down-main\">\n <stream-icon icon=\"connection-error\"></stream-icon>\n <h1>{{ \"streamChat.Connection error\" | translate }}</h1>\n <h3>\n {{\n \"streamChat.Error connecting to chat, refresh the page to try again.\"\n | translate\n }}\n </h3>\n </div>\n </div>\n</ng-template>\n\n<ng-template #loadingChannels>\n <div data-testid=\"loading-indicator\" class=\"str-chat__loading-channels\">\n <ng-container *ngTemplateOutlet=\"loadingChannel\"></ng-container>\n <ng-container *ngTemplateOutlet=\"loadingChannel\"></ng-container>\n <ng-container *ngTemplateOutlet=\"loadingChannel\"></ng-container>\n </div>\n</ng-template>\n\n<ng-template #loadingChannel>\n <div class=\"str-chat__loading-channels-item\">\n <div class=\"str-chat__loading-channels-avatar\"></div>\n <div class=\"str-chat__loading-channels-meta\">\n <div class=\"str-chat__loading-channels-username\"></div>\n <div class=\"str-chat__loading-channels-status\"></div>\n </div>\n </div>\n</ng-template>\n", components: [{ type: ChannelPreviewComponent, selector: "stream-channel-preview", inputs: ["channel"] }, { type: LoadingIndicatorComponent, selector: "stream-loading-indicator", inputs: ["size", "color"] }, { type: IconComponent, selector: "stream-icon", inputs: ["icon", "size"] }], directives: [{ type:
|
|
2157
|
+
ChannelListComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.5", type: ChannelListComponent, selector: "stream-channel-list", inputs: { customChannelPreviewTemplate: "customChannelPreviewTemplate" }, viewQueries: [{ propertyName: "container", first: true, predicate: ["container"], descendants: true }], ngImport: i0, template: "<div\n #container\n data-testid=\"channel-list-container\"\n class=\"str-chat str-chat-channel-list messaging\"\n [class.str-chat-channel-list--open]=\"(isOpen$ | async) === true\"\n>\n <div\n *ngIf=\"\n (isError$ | async) === false && (isInitializing$ | async) === false;\n else statusIndicator\n \"\n class=\"str-chat__channel-list-messenger\"\n >\n <div class=\"str-chat__channel-list-messenger__main\">\n <p\n data-testid=\"empty-channel-list-indicator\"\n *ngIf=\"!(channels$ | async)?.length\"\n >\n {{ \"streamChat.You have no channels currently\" | translate }}\n </p>\n <ng-container\n *ngFor=\"let channel of channels$ | async; trackBy: trackByChannelId\"\n >\n <ng-container\n *ngIf=\"customChannelPreviewTemplate; else defaultTemplate\"\n >\n <div (click)=\"channelSelected()\" (keyup.enter)=\"channelSelected()\">\n <ng-container\n *ngTemplateOutlet=\"\n customChannelPreviewTemplate;\n context: { channel: channel }\n \"\n ></ng-container>\n </div>\n </ng-container>\n <ng-template #defaultTemplate>\n <stream-channel-preview\n data-testclass=\"channel-preview\"\n [channel]=\"channel\"\n (click)=\"channelSelected()\"\n (keyup.enter)=\"channelSelected()\"\n ></stream-channel-preview>\n </ng-template>\n </ng-container>\n <div\n *ngIf=\"hasMoreChannels$ | async\"\n class=\"str-chat__load-more-button\"\n (click)=\"loadMoreChannels()\"\n (keyup.enter)=\"loadMoreChannels()\"\n data-testid=\"load-more\"\n >\n <button\n class=\"str-chat__load-more-button__button\"\n data-testid=\"load-more-button\"\n [disabled]=\"isLoadingMoreChannels\"\n >\n <span *ngIf=\"!isLoadingMoreChannels; else loadingIndicator\">{{\n \"Load more\" | translate\n }}</span>\n <ng-template #loadingIndicator\n ><stream-loading-indicator></stream-loading-indicator\n ></ng-template>\n </button>\n </div>\n </div>\n </div>\n</div>\n\n<ng-template #statusIndicator>\n <ng-container *ngIf=\"isError$ | async\">\n <ng-container *ngTemplateOutlet=\"chatDown\"></ng-container>\n </ng-container>\n <ng-container *ngIf=\"isInitializing$ | async\">\n <ng-container *ngTemplateOutlet=\"loadingChannels\"></ng-container>\n </ng-container>\n</ng-template>\n\n<ng-template #chatDown>\n <div data-testid=\"chatdown-container\" class=\"str-chat__down\">\n <ng-container *ngTemplateOutlet=\"loadingChannels\"></ng-container>\n <div class=\"str-chat__down-main\">\n <stream-icon icon=\"connection-error\"></stream-icon>\n <h1>{{ \"streamChat.Connection error\" | translate }}</h1>\n <h3>\n {{\n \"streamChat.Error connecting to chat, refresh the page to try again.\"\n | translate\n }}\n </h3>\n </div>\n </div>\n</ng-template>\n\n<ng-template #loadingChannels>\n <div data-testid=\"loading-indicator\" class=\"str-chat__loading-channels\">\n <ng-container *ngTemplateOutlet=\"loadingChannel\"></ng-container>\n <ng-container *ngTemplateOutlet=\"loadingChannel\"></ng-container>\n <ng-container *ngTemplateOutlet=\"loadingChannel\"></ng-container>\n </div>\n</ng-template>\n\n<ng-template #loadingChannel>\n <div class=\"str-chat__loading-channels-item\">\n <div class=\"str-chat__loading-channels-avatar\"></div>\n <div class=\"str-chat__loading-channels-meta\">\n <div class=\"str-chat__loading-channels-username\"></div>\n <div class=\"str-chat__loading-channels-status\"></div>\n </div>\n </div>\n</ng-template>\n", components: [{ type: ChannelPreviewComponent, selector: "stream-channel-preview", inputs: ["channel"] }, { type: LoadingIndicatorComponent, selector: "stream-loading-indicator", inputs: ["size", "color"] }, { type: IconComponent, selector: "stream-icon", inputs: ["icon", "size"] }], directives: [{ type: i6.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i6.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i6.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet"] }], pipes: { "async": i6.AsyncPipe, "translate": i10.TranslatePipe } });
|
|
1960
2158
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: ChannelListComponent, decorators: [{
|
|
1961
2159
|
type: Component,
|
|
1962
2160
|
args: [{
|
|
@@ -2107,7 +2305,7 @@ class MessageReactionsComponent {
|
|
|
2107
2305
|
}
|
|
2108
2306
|
}
|
|
2109
2307
|
MessageReactionsComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: MessageReactionsComponent, deps: [{ token: i0.ChangeDetectorRef }, { token: ChannelService }], target: i0.ɵɵFactoryTarget.Component });
|
|
2110
|
-
MessageReactionsComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.5", type: MessageReactionsComponent, selector: "stream-message-reactions", inputs: { messageId: "messageId", messageReactionCounts: "messageReactionCounts", isSelectorOpen: "isSelectorOpen", latestReactions: "latestReactions", ownReactions: "ownReactions" }, outputs: { isSelectorOpenChange: "isSelectorOpenChange" }, viewQueries: [{ propertyName: "selectorContainer", first: true, predicate: ["selectorContainer"], descendants: true }, { propertyName: "selectorTooltip", first: true, predicate: ["selectorTooltip"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div\n *ngIf=\"existingReactions.length > 0 && !isSelectorOpen\"\n class=\"str-chat__reaction-list\"\n [class.str-chat__reaction-list--reverse]=\"true\"\n data-testid=\"reaction-list\"\n>\n <ul>\n <li\n *ngFor=\"\n let reactionType of existingReactions;\n trackBy: trackByMessageReaction\n \"\n data-testclass=\"emoji\"\n >\n <span class=\"emoji\">\n {{ getEmojiByReaction(reactionType) }}\n </span>\n \n </li>\n <li>\n <span\n data-testid=\"reactions-count\"\n class=\"str-chat__reaction-list--counter\"\n >{{ reactionsCount }}</span\n >\n </li>\n </ul>\n</div>\n\n<div\n #selectorContainer\n class=\"str-chat__reaction-selector\"\n *ngIf=\"isSelectorOpen\"\n data-testid=\"reaction-selector\"\n>\n <div\n *ngIf=\"tooltipText\"\n data-testid=\"tooltip\"\n #selectorTooltip\n class=\"str-chat__reaction-selector-tooltip\"\n [ngStyle]=\"{\n left: tooltipPositions?.tooltip + 'px',\n visibility: tooltipPositions ? 'visible' : 'hidden'\n }\"\n >\n <div\n class=\"arrow\"\n [ngStyle]=\"{ left: tooltipPositions?.arrow + 'px' }\"\n ></div>\n <span class=\"latest-user-username\">\n {{ tooltipText }}\n </span>\n </div>\n <ul class=\"str-chat__message-reactions-list\">\n <li\n class=\"str-chat__message-reactions-list-item\"\n *ngFor=\"\n let reactionType of reactionOptions;\n trackBy: trackByMessageReaction\n \"\n data-testclass=\"emoji-option\"\n (click)=\"react(reactionType)\"\n (keyup.enter)=\"react(reactionType)\"\n >\n <div\n *ngIf=\"getLatestUserByReaction(reactionType) as user\"\n class=\"latest-user\"\n (click)=\"hideTooltip()\"\n (keyup.enter)=\"hideTooltip()\"\n (mouseenter)=\"showTooltip($event, reactionType)\"\n (mouseleave)=\"hideTooltip()\"\n attr.data-testid=\"{{ reactionType }}-last-user\"\n >\n <stream-avatar\n attr.data-testid=\"{{ reactionType }}-avatar\"\n [imageUrl]=\"user.image\"\n [name]=\"user.name || user.id\"\n [size]=\"20\"\n ></stream-avatar>\n </div>\n <span class=\"emoji\" style=\"width: 20px; height: 20px; top: 10px\">\n {{ getEmojiByReaction(reactionType) }}\n </span>\n <span\n *ngIf=\"\n messageReactionCounts[reactionType] &&\n messageReactionCounts[reactionType]! > 0\n \"\n class=\"str-chat__message-reactions-list-item__count\"\n attr.data-testid=\"{{ reactionType }}-reaction-count\"\n >\n {{ messageReactionCounts[reactionType] }}\n </span>\n </li>\n </ul>\n</div>\n", styles: [".emoji {position: relative; display: inline-block; }"], components: [{ type: AvatarComponent, selector: "stream-avatar", inputs: ["name", "imageUrl", "size"] }], directives: [{ type:
|
|
2308
|
+
MessageReactionsComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.5", type: MessageReactionsComponent, selector: "stream-message-reactions", inputs: { messageId: "messageId", messageReactionCounts: "messageReactionCounts", isSelectorOpen: "isSelectorOpen", latestReactions: "latestReactions", ownReactions: "ownReactions" }, outputs: { isSelectorOpenChange: "isSelectorOpenChange" }, viewQueries: [{ propertyName: "selectorContainer", first: true, predicate: ["selectorContainer"], descendants: true }, { propertyName: "selectorTooltip", first: true, predicate: ["selectorTooltip"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div\n *ngIf=\"existingReactions.length > 0 && !isSelectorOpen\"\n class=\"str-chat__reaction-list\"\n [class.str-chat__reaction-list--reverse]=\"true\"\n data-testid=\"reaction-list\"\n>\n <ul>\n <li\n *ngFor=\"\n let reactionType of existingReactions;\n trackBy: trackByMessageReaction\n \"\n data-testclass=\"emoji\"\n >\n <span class=\"emoji\">\n {{ getEmojiByReaction(reactionType) }}\n </span>\n \n </li>\n <li>\n <span\n data-testid=\"reactions-count\"\n class=\"str-chat__reaction-list--counter\"\n >{{ reactionsCount }}</span\n >\n </li>\n </ul>\n</div>\n\n<div\n #selectorContainer\n class=\"str-chat__reaction-selector\"\n *ngIf=\"isSelectorOpen\"\n data-testid=\"reaction-selector\"\n>\n <div\n *ngIf=\"tooltipText\"\n data-testid=\"tooltip\"\n #selectorTooltip\n class=\"str-chat__reaction-selector-tooltip\"\n [ngStyle]=\"{\n left: tooltipPositions?.tooltip + 'px',\n visibility: tooltipPositions ? 'visible' : 'hidden'\n }\"\n >\n <div\n class=\"arrow\"\n [ngStyle]=\"{ left: tooltipPositions?.arrow + 'px' }\"\n ></div>\n <span class=\"latest-user-username\">\n {{ tooltipText }}\n </span>\n </div>\n <ul class=\"str-chat__message-reactions-list\">\n <li\n class=\"str-chat__message-reactions-list-item\"\n *ngFor=\"\n let reactionType of reactionOptions;\n trackBy: trackByMessageReaction\n \"\n data-testclass=\"emoji-option\"\n (click)=\"react(reactionType)\"\n (keyup.enter)=\"react(reactionType)\"\n >\n <div\n *ngIf=\"getLatestUserByReaction(reactionType) as user\"\n class=\"latest-user\"\n (click)=\"hideTooltip()\"\n (keyup.enter)=\"hideTooltip()\"\n (mouseenter)=\"showTooltip($event, reactionType)\"\n (mouseleave)=\"hideTooltip()\"\n attr.data-testid=\"{{ reactionType }}-last-user\"\n >\n <stream-avatar\n attr.data-testid=\"{{ reactionType }}-avatar\"\n [imageUrl]=\"user.image\"\n [name]=\"user.name || user.id\"\n [size]=\"20\"\n ></stream-avatar>\n </div>\n <span class=\"emoji\" style=\"width: 20px; height: 20px; top: 10px\">\n {{ getEmojiByReaction(reactionType) }}\n </span>\n <span\n *ngIf=\"\n messageReactionCounts[reactionType] &&\n messageReactionCounts[reactionType]! > 0\n \"\n class=\"str-chat__message-reactions-list-item__count\"\n attr.data-testid=\"{{ reactionType }}-reaction-count\"\n >\n {{ messageReactionCounts[reactionType] }}\n </span>\n </li>\n </ul>\n</div>\n", styles: [".emoji {position: relative; display: inline-block; }"], components: [{ type: AvatarComponent, selector: "stream-avatar", inputs: ["name", "imageUrl", "size"] }], directives: [{ type: i6.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i6.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i6.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }] });
|
|
2111
2309
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: MessageReactionsComponent, decorators: [{
|
|
2112
2310
|
type: Component,
|
|
2113
2311
|
args: [{
|
|
@@ -2150,8 +2348,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImpor
|
|
|
2150
2348
|
}], ctorParameters: function () { return []; } });
|
|
2151
2349
|
|
|
2152
2350
|
class AttachmentListComponent {
|
|
2153
|
-
constructor(imageLoadService) {
|
|
2351
|
+
constructor(imageLoadService, channelService) {
|
|
2154
2352
|
this.imageLoadService = imageLoadService;
|
|
2353
|
+
this.channelService = channelService;
|
|
2155
2354
|
this.attachments = [];
|
|
2156
2355
|
this.orderedAttachments = [];
|
|
2157
2356
|
}
|
|
@@ -2173,7 +2372,8 @@ class AttachmentListComponent {
|
|
|
2173
2372
|
}
|
|
2174
2373
|
isCard(attachment) {
|
|
2175
2374
|
return (!attachment.type ||
|
|
2176
|
-
(attachment.type === 'image' && !this.isImage(attachment))
|
|
2375
|
+
(attachment.type === 'image' && !this.isImage(attachment)) ||
|
|
2376
|
+
attachment.type === 'giphy');
|
|
2177
2377
|
}
|
|
2178
2378
|
imageLoaded() {
|
|
2179
2379
|
this.imageLoadService.imageLoad$.next();
|
|
@@ -2193,9 +2393,17 @@ class AttachmentListComponent {
|
|
|
2193
2393
|
}
|
|
2194
2394
|
return null;
|
|
2195
2395
|
}
|
|
2396
|
+
sendAction(action) {
|
|
2397
|
+
void this.channelService.sendAction(this.messageId, {
|
|
2398
|
+
[action.name]: action.value,
|
|
2399
|
+
});
|
|
2400
|
+
}
|
|
2401
|
+
trackByActionValue(_, item) {
|
|
2402
|
+
return item.value;
|
|
2403
|
+
}
|
|
2196
2404
|
}
|
|
2197
|
-
AttachmentListComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: AttachmentListComponent, deps: [{ token: ImageLoadService }], target: i0.ɵɵFactoryTarget.Component });
|
|
2198
|
-
AttachmentListComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.5", type: AttachmentListComponent, selector: "stream-attachment-list", inputs: { attachments: "attachments" }, usesOnChanges: true, ngImport: i0, template: "<ng-container *ngFor=\"let attachment of orderedAttachments; trackBy: trackById\">\n <div\n data-testclass=\"attachment-container\"\n class=\"str-chat__message-attachment str-chat__message-attachment--{{\n attachment.type\n }}\"\n [class.str-chat__message-attachment--card]=\"isCard(attachment)\"\n [class.str-chat-angular__message-attachment-file-single]=\"\n isFile(attachment)\n \"\n >\n <img\n *ngIf=\"isImage(attachment)\"\n class=\"str-chat__message-attachment--img\"\n data-testclass=\"image\"\n [src]=\"attachment.img_url || attachment.thumb_url || attachment.image_url\"\n [alt]=\"attachment?.fallback\"\n (load)=\"imageLoaded()\"\n />\n <div\n *ngIf=\"isFile(attachment)\"\n class=\"\n str-chat__message-attachment-file--item\n str-chat-angular__message-attachment-file-single\n \"\n >\n <stream-icon icon=\"file\" [size]=\"30\"></stream-icon>\n <div class=\"str-chat__message-attachment-file--item-text\">\n <a\n data-testclass=\"file-link\"\n download\n href=\"{{ attachment.asset_url }}\"\n target=\"_blank\"\n >\n {{ attachment.title }}\n </a>\n <span data-testclass=\"size\" *ngIf=\"hasFileSize(attachment)\">{{\n getFileSize(attachment)\n }}</span>\n </div>\n </div>\n <div\n *ngIf=\"isCard(attachment)\"\n class=\"str-chat__message-attachment-card str-chat__message-attachment-card--{{\n attachment.type\n }}\"\n >\n <div\n *ngIf=\"attachment.image_url || attachment.thumb_url\"\n class=\"str-chat__message-attachment-card--header\"\n >\n <img\n data-testclass=\"card-img\"\n alt=\"{{ attachment.image_url || attachment.thumb_url }}\"\n src=\"{{ attachment.image_url || attachment.thumb_url }}\"\n />\n </div>\n <div class=\"str-chat__message-attachment-card--content\">\n <div class=\"str-chat__message-attachment-card--flex\">\n <div\n *ngIf=\"attachment.title\"\n data-testclass=\"card-title\"\n class=\"str-chat__message-attachment-card--title\"\n >\n {{ attachment.title }}\n </div>\n <div\n *ngIf=\"attachment.text\"\n class=\"str-chat__message-attachment-card--text\"\n data-testclass=\"card-text\"\n >\n {{ attachment.text }}\n </div>\n <a\n class=\"str-chat__message-attachment-card--url\"\n *ngIf=\"attachment.title_link || attachment.og_scrape_url\"\n data-testclass=\"url-link\"\n noopener\n noreferrer\n href=\"{{ attachment.title_link || attachment.og_scrape_url }}\"\n target=\"_blank\"\n >\n {{ trimUrl(attachment.title_link || attachment.og_scrape_url) }}\n </a>\n </div>\n </div>\n </div>\n </div>\n</ng-container>\n", components: [{ type: IconComponent, selector: "stream-icon", inputs: ["icon", "size"] }], directives: [{ type:
|
|
2405
|
+
AttachmentListComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: AttachmentListComponent, deps: [{ token: ImageLoadService }, { token: ChannelService }], target: i0.ɵɵFactoryTarget.Component });
|
|
2406
|
+
AttachmentListComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.5", type: AttachmentListComponent, selector: "stream-attachment-list", inputs: { messageId: "messageId", attachments: "attachments" }, usesOnChanges: true, ngImport: i0, template: "<ng-container *ngFor=\"let attachment of orderedAttachments; trackBy: trackById\">\n <div\n data-testclass=\"attachment-container\"\n class=\"str-chat__message-attachment str-chat__message-attachment--{{\n attachment.type\n }}\"\n [class.str-chat__message-attachment--card]=\"isCard(attachment)\"\n [class.str-chat-angular__message-attachment-file-single]=\"\n isFile(attachment)\n \"\n >\n <img\n *ngIf=\"isImage(attachment)\"\n class=\"str-chat__message-attachment--img\"\n data-testclass=\"image\"\n [src]=\"attachment.img_url || attachment.thumb_url || attachment.image_url\"\n [alt]=\"attachment?.fallback\"\n (load)=\"imageLoaded()\"\n />\n <div\n *ngIf=\"isFile(attachment)\"\n class=\"\n str-chat__message-attachment-file--item\n str-chat-angular__message-attachment-file-single\n \"\n >\n <stream-icon icon=\"file\" [size]=\"30\"></stream-icon>\n <div class=\"str-chat__message-attachment-file--item-text\">\n <a\n data-testclass=\"file-link\"\n download\n href=\"{{ attachment.asset_url }}\"\n target=\"_blank\"\n >\n {{ attachment.title }}\n </a>\n <span data-testclass=\"size\" *ngIf=\"hasFileSize(attachment)\">{{\n getFileSize(attachment)\n }}</span>\n </div>\n </div>\n <div\n *ngIf=\"isCard(attachment)\"\n class=\"str-chat__message-attachment-card str-chat__message-attachment-card--{{\n attachment.type\n }}\"\n >\n <div\n *ngIf=\"attachment.image_url || attachment.thumb_url\"\n class=\"str-chat__message-attachment-card--header\"\n >\n <img\n data-testclass=\"card-img\"\n alt=\"{{ attachment.image_url || attachment.thumb_url }}\"\n src=\"{{ attachment.image_url || attachment.thumb_url }}\"\n />\n </div>\n <div class=\"str-chat__message-attachment-card--content\">\n <div class=\"str-chat__message-attachment-card--flex\">\n <div\n *ngIf=\"attachment.title\"\n data-testclass=\"card-title\"\n class=\"str-chat__message-attachment-card--title\"\n >\n {{ attachment.title }}\n </div>\n <div\n *ngIf=\"attachment.text\"\n class=\"str-chat__message-attachment-card--text\"\n data-testclass=\"card-text\"\n >\n {{ attachment.text }}\n </div>\n <a\n class=\"str-chat__message-attachment-card--url\"\n *ngIf=\"attachment.title_link || attachment.og_scrape_url\"\n data-testclass=\"url-link\"\n noopener\n noreferrer\n href=\"{{ attachment.title_link || attachment.og_scrape_url }}\"\n target=\"_blank\"\n >\n {{ trimUrl(attachment.title_link || attachment.og_scrape_url) }}\n </a>\n </div>\n </div>\n </div>\n <div\n class=\"str-chat__message-attachment-actions\"\n *ngIf=\"attachment.actions && attachment.actions.length > 0\"\n >\n <div class=\"str-chat__message-attachment-actions-form\">\n <button\n *ngFor=\"let action of attachment.actions; trackBy: trackByActionValue\"\n class=\"str-chat__message-attachment-actions-button str-chat__message-attachment-actions-button--{{\n action.style\n }}\"\n data-testclass=\"attachment-action\"\n (click)=\"sendAction(action)\"\n (keyup.enter)=\"sendAction(action)\"\n >\n {{ action.text }}\n </button>\n </div>\n </div>\n </div>\n</ng-container>\n", components: [{ type: IconComponent, selector: "stream-icon", inputs: ["icon", "size"] }], directives: [{ type: i6.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i6.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }] });
|
|
2199
2407
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: AttachmentListComponent, decorators: [{
|
|
2200
2408
|
type: Component,
|
|
2201
2409
|
args: [{
|
|
@@ -2203,7 +2411,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImpor
|
|
|
2203
2411
|
templateUrl: './attachment-list.component.html',
|
|
2204
2412
|
styles: [],
|
|
2205
2413
|
}]
|
|
2206
|
-
}], ctorParameters: function () { return [{ type: ImageLoadService }]; }, propDecorators: {
|
|
2414
|
+
}], ctorParameters: function () { return [{ type: ImageLoadService }, { type: ChannelService }]; }, propDecorators: { messageId: [{
|
|
2415
|
+
type: Input
|
|
2416
|
+
}], attachments: [{
|
|
2207
2417
|
type: Input
|
|
2208
2418
|
}] } });
|
|
2209
2419
|
|
|
@@ -2212,6 +2422,7 @@ class MessageComponent {
|
|
|
2212
2422
|
this.chatClientService = chatClientService;
|
|
2213
2423
|
this.channelService = channelService;
|
|
2214
2424
|
this.enabledMessageActions = [];
|
|
2425
|
+
this.mode = 'main';
|
|
2215
2426
|
this.isActionBoxOpen = false;
|
|
2216
2427
|
this.isReactionSelectorOpen = false;
|
|
2217
2428
|
this.isPressedOnMobile = false;
|
|
@@ -2301,7 +2512,8 @@ class MessageComponent {
|
|
|
2301
2512
|
this.message.type === 'system' ||
|
|
2302
2513
|
this.message.type === 'ephemeral' ||
|
|
2303
2514
|
this.message.status === 'failed' ||
|
|
2304
|
-
this.message.status === 'sending'
|
|
2515
|
+
this.message.status === 'sending' ||
|
|
2516
|
+
(this.mode === 'thread' && !this.message.parent_id));
|
|
2305
2517
|
}
|
|
2306
2518
|
get hasAttachment() {
|
|
2307
2519
|
var _a;
|
|
@@ -2312,6 +2524,14 @@ class MessageComponent {
|
|
|
2312
2524
|
return (!!((_a = this.message) === null || _a === void 0 ? void 0 : _a.reaction_counts) &&
|
|
2313
2525
|
Object.keys(this.message.reaction_counts).length > 0);
|
|
2314
2526
|
}
|
|
2527
|
+
get replyCountParam() {
|
|
2528
|
+
var _a;
|
|
2529
|
+
return { replyCount: (_a = this.message) === null || _a === void 0 ? void 0 : _a.reply_count };
|
|
2530
|
+
}
|
|
2531
|
+
get canDisplayReadStatus() {
|
|
2532
|
+
return (this.canReceiveReadEvents !== false &&
|
|
2533
|
+
this.enabledMessageActions.indexOf('read-events') !== -1);
|
|
2534
|
+
}
|
|
2315
2535
|
resendMessage() {
|
|
2316
2536
|
void this.channelService.resendMessage(this.message);
|
|
2317
2537
|
}
|
|
@@ -2333,9 +2553,12 @@ class MessageComponent {
|
|
|
2333
2553
|
};
|
|
2334
2554
|
window.addEventListener('click', eventHandler);
|
|
2335
2555
|
}
|
|
2556
|
+
setAsActiveParentMessage() {
|
|
2557
|
+
void this.channelService.setAsActiveParentMessage(this.message);
|
|
2558
|
+
}
|
|
2336
2559
|
}
|
|
2337
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 });
|
|
2338
|
-
MessageComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.5", type: MessageComponent, selector: "stream-message", inputs: { messageInputTemplate: "messageInputTemplate", mentionTemplate: "mentionTemplate", message: "message", enabledMessageActions: "enabledMessageActions", areReactionsEnabled: "areReactionsEnabled", canReactToMessage: "canReactToMessage", isLastSentMessage: "isLastSentMessage", canReceiveReadEvents: "canReceiveReadEvents" }, viewQueries: [{ propertyName: "container", first: true, predicate: ["container"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div\n #container\n class=\"str-chat__message-simple str-chat__message str-chat__message--{{\n message?.type\n }} str-chat__message--{{ message?.status }} {{\n message?.text ? 'str-chat__message--has-text' : 'has-no-text'\n }}\"\n [class.str-chat__message--me]=\"isSentByCurrentUser\"\n [class.str-chat__message-simple--me]=\"isSentByCurrentUser\"\n [class.mobile-press]=\"isPressedOnMobile\"\n [class.str-chat__message--has-attachment]=\"hasAttachment\"\n [class.str-chat__message--with-reactions]=\"\n areReactionsEnabled && hasReactions\n \"\n data-testid=\"message-container\"\n>\n <ng-container *ngIf=\"!message?.deleted_at; else deletedMessage\">\n <ng-container *ngIf=\"message?.type !== 'system'; else systemMessage\">\n <ng-container\n *ngIf=\"\n isSentByCurrentUser &&\n ((isLastSentMessage && message?.status === 'received') ||\n message?.status === 'sending')\n \"\n >\n <ng-container *ngIf=\"message?.status === 'sending'; else sentStatus\">\n <ng-container *ngTemplateOutlet=\"sendingStatus\"></ng-container>\n </ng-container>\n <ng-template #sentStatus>\n <ng-container\n *ngIf=\"\n isMessageDeliveredAndRead && canReceiveReadEvents;\n else deliveredStatus\n \"\n >\n <ng-container *ngTemplateOutlet=\"readStatus\"></ng-container>\n </ng-container>\n </ng-template>\n </ng-container>\n <stream-avatar\n data-testid=\"avatar\"\n class=\"str-chat-angular__avatar-host\"\n [imageUrl]=\"message?.user?.image\"\n [name]=\"message?.user?.name || message?.user?.id\"\n ></stream-avatar>\n <div class=\"str-chat__message-inner\">\n <div\n class=\"str-chat__message-simple__actions\"\n data-testid=\"message-options\"\n *ngIf=\"areOptionsVisible\"\n >\n <div\n data-testid=\"message-actions-container\"\n class=\"\n str-chat__message-simple__actions__action\n str-chat__message-simple__actions__action--options\n \"\n [class.str-chat-angular__message-simple__actions__action--options--editing]=\"\n isEditing\n \"\n >\n <stream-message-actions-box\n [isOpen]=\"isActionBoxOpen\"\n [isMine]=\"isSentByCurrentUser\"\n [enabledActions]=\"enabledMessageActions\"\n [message]=\"message\"\n (displayedActionsCount)=\"visibleMessageActionsCount = $event\"\n (isEditing)=\"isEditing = $event; isActionBoxOpen = !isEditing\"\n [messageInputTemplate]=\"messageInputTemplate\"\n ></stream-message-actions-box>\n <stream-icon\n *ngIf=\"visibleMessageActionsCount > 0\"\n data-testid=\"action-icon\"\n icon=\"action-icon\"\n (keyup.enter)=\"isActionBoxOpen = !isActionBoxOpen\"\n (click)=\"isActionBoxOpen = !isActionBoxOpen\"\n ></stream-icon>\n </div>\n <div\n *ngIf=\"areReactionsEnabled && canReactToMessage\"\n class=\"\n str-chat__message-simple__actions__action\n str-chat__message-simple__actions__action--reactions\n \"\n data-testid=\"reaction-icon\"\n (click)=\"isReactionSelectorOpen = !isReactionSelectorOpen\"\n (keyup.enter)=\"isReactionSelectorOpen = !isReactionSelectorOpen\"\n >\n <stream-icon icon=\"reaction-icon\"></stream-icon>\n </div>\n </div>\n <stream-message-reactions\n *ngIf=\"areReactionsEnabled\"\n [messageReactionCounts]=\"message?.reaction_counts || {}\"\n [latestReactions]=\"message?.latest_reactions || []\"\n [(isSelectorOpen)]=\"isReactionSelectorOpen\"\n [messageId]=\"message?.id\"\n [ownReactions]=\"message?.own_reactions || []\"\n ></stream-message-reactions>\n <stream-attachment-list\n *ngIf=\"hasAttachment\"\n [attachments]=\"message!.attachments!\"\n ></stream-attachment-list>\n <div class=\"str-chat__message-text\" *ngIf=\"message?.text\">\n <div\n data-testid=\"inner-message\"\n class=\"\n str-chat__message-text-inner str-chat__message-simple-text-inner\n \"\n [class.str-chat__message-light-text-inner--has-attachment]=\"\n hasAttachment\n \"\n (click)=\"\n message?.status === 'failed' && message?.errorStatusCode !== 403\n ? resendMessage()\n : undefined\n \"\n (keyup.enter)=\"\n message?.status === 'failed' && message?.errorStatusCode !== 403\n ? resendMessage()\n : undefined\n \"\n >\n <div\n data-testid=\"client-error-message\"\n *ngIf=\"message?.type === 'error'\"\n class=\"str-chat__simple-message--error-message\"\n >\n {{ \"streamChat.Error \u00B7 Unsent\" | translate }}\n </div>\n <div\n data-testid=\"error-message\"\n *ngIf=\"message?.status === 'failed'\"\n class=\"str-chat__simple-message--error-message\"\n >\n {{\n (message?.errorStatusCode === 403\n ? \"streamChat.Message Failed \u00B7 Unauthorized\"\n : \"streamChat.Message Failed \u00B7 Click to try again\"\n ) | translate\n }}\n </div>\n <div\n (click)=\"textClicked()\"\n (keyup.enter)=\"textClicked()\"\n data-testid=\"text\"\n >\n <p>\n <!-- eslint-disable-next-line @angular-eslint/template/use-track-by-function -->\n <ng-container *ngFor=\"let part of messageTextParts\">\n <span\n *ngIf=\"part.type === 'text'; else mention\"\n [innerHTML]=\"part.content\"\n ></span>\n <ng-template #mention>\n <ng-container *ngIf=\"mentionTemplate; else defaultMention\">\n <ng-container\n *ngTemplateOutlet=\"\n mentionTemplate;\n context: { user: part.user! }\n \"\n ></ng-container>\n </ng-container>\n <ng-template #defaultMention>\n <b>{{ part.content }}</b>\n </ng-template>\n </ng-template>\n </ng-container>\n </p>\n </div>\n </div>\n </div>\n <div class=\"str-chat__message-data str-chat__message-simple-data\">\n <span\n data-testid=\"sender\"\n *ngIf=\"!isSentByCurrentUser\"\n class=\"str-chat__message-simple-name\"\n >\n {{ message?.user?.name ? message?.user?.name : message?.user?.id }}\n </span>\n <span data-testid=\"date\" class=\"str-chat__message-simple-timestamp\">\n {{ parsedDate }}\n </span>\n </div>\n </div>\n </ng-container>\n </ng-container>\n</div>\n\n<ng-template #sendingStatus>\n <span\n class=\"\n str-chat__message-simple-status str-chat__message-simple-status-angular\n \"\n data-testid=\"sending-indicator\"\n >\n <div class=\"str-chat__tooltip\">\n {{ \"streamChat.Sending...\" | translate }}\n </div>\n <stream-loading-indicator\n data-testid=\"loading-indicator\"\n ></stream-loading-indicator>\n </span>\n</ng-template>\n<ng-template #readStatus>\n <span\n class=\"\n str-chat__message-simple-status str-chat__message-simple-status-angular\n \"\n data-testid=\"read-indicator\"\n >\n <div class=\"str-chat__tooltip\" data-testid=\"read-by-tooltip\">\n {{ readByText }}\n </div>\n <stream-avatar\n class=\"str-chat-angular__avatar-host\"\n data-test-id=\"last-read-user-avatar\"\n [size]=\"15\"\n [imageUrl]=\"lastReadUser?.image\"\n [name]=\"lastReadUser?.name || lastReadUser?.id\"\n ></stream-avatar>\n <span\n data-test-id=\"read-by-length\"\n *ngIf=\"isReadByMultipleUsers\"\n class=\"str-chat__message-simple-status-number\"\n >\n {{ (message?.readBy)!.length }}\n </span>\n </span>\n</ng-template>\n<ng-template #deliveredStatus>\n <span\n class=\"\n str-chat__message-simple-status str-chat__message-simple-status-angular\n \"\n data-testid=\"delivered-indicator\"\n >\n <div class=\"str-chat__tooltip\">\n {{ \"streamChat.Delivered\" | translate }}\n </div>\n <stream-icon\n data-testid=\"delivered-icon\"\n icon=\"delivered-icon\"\n ></stream-icon>\n </span>\n</ng-template>\n\n<ng-template #deletedMessage>\n <div data-testid=\"message-deleted-component\">\n <div class=\"str-chat__message--deleted-inner\" translate>\n streamChat.This message was deleted...\n </div>\n </div>\n</ng-template>\n\n<ng-template #systemMessage>\n <div data-testid=\"system-message\" class=\"str-chat__message--system\">\n <div class=\"str-chat__message--system__text\">\n <div class=\"str-chat__message--system__line\"></div>\n <p>{{ message?.text }}</p>\n <div class=\"str-chat__message--system__line\"></div>\n </div>\n <div class=\"str-chat__message--system__date\">\n {{ parsedDate }}\n </div>\n </div>\n</ng-template>\n", components: [{ type: AvatarComponent, selector: "stream-avatar", inputs: ["name", "imageUrl", "size"] }, { type: MessageActionsBoxComponent, selector: "stream-message-actions-box", inputs: ["messageInputTemplate", "isOpen", "isMine", "message", "enabledActions"], outputs: ["displayedActionsCount", "isEditing"] }, { type: IconComponent, selector: "stream-icon", inputs: ["icon", "size"] }, { type: MessageReactionsComponent, selector: "stream-message-reactions", inputs: ["messageId", "messageReactionCounts", "isSelectorOpen", "latestReactions", "ownReactions"], outputs: ["isSelectorOpenChange"] }, { type: AttachmentListComponent, selector: "stream-attachment-list", inputs: ["attachments"] }, { type: LoadingIndicatorComponent, selector: "stream-loading-indicator", inputs: ["size", "color"] }], directives: [{ type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i3.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet"] }, { type: i3.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i10.TranslateDirective, selector: "[translate],[ngx-translate]", inputs: ["translate", "translateParams"] }], pipes: { "translate": i10.TranslatePipe } });
|
|
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 } });
|
|
2339
2562
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: MessageComponent, decorators: [{
|
|
2340
2563
|
type: Component,
|
|
2341
2564
|
args: [{
|
|
@@ -2359,6 +2582,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImpor
|
|
|
2359
2582
|
type: Input
|
|
2360
2583
|
}], canReceiveReadEvents: [{
|
|
2361
2584
|
type: Input
|
|
2585
|
+
}], mode: [{
|
|
2586
|
+
type: Input
|
|
2362
2587
|
}], container: [{
|
|
2363
2588
|
type: ViewChild,
|
|
2364
2589
|
args: ['container']
|
|
@@ -2428,8 +2653,9 @@ class AutocompleteTextareaComponent {
|
|
|
2428
2653
|
this.valueChange = new EventEmitter();
|
|
2429
2654
|
this.send = new EventEmitter();
|
|
2430
2655
|
this.userMentions = new EventEmitter();
|
|
2431
|
-
this.
|
|
2656
|
+
this.autocompleteKey = 'autocompleteLabel';
|
|
2432
2657
|
this.mentionTriggerChar = '@';
|
|
2658
|
+
this.commandTriggerChar = '/';
|
|
2433
2659
|
this.autocompleteConfig = {
|
|
2434
2660
|
mentions: [],
|
|
2435
2661
|
};
|
|
@@ -2438,7 +2664,15 @@ class AutocompleteTextareaComponent {
|
|
|
2438
2664
|
this.userMentionConfig = {
|
|
2439
2665
|
triggerChar: this.mentionTriggerChar,
|
|
2440
2666
|
dropUp: true,
|
|
2441
|
-
labelKey: this.
|
|
2667
|
+
labelKey: this.autocompleteKey,
|
|
2668
|
+
returnTrigger: true,
|
|
2669
|
+
mentionFilter: (searchString, items) => this.filter(searchString, items),
|
|
2670
|
+
mentionSelect: (item, triggerChar) => this.itemSelectedFromAutocompleteList(item, triggerChar),
|
|
2671
|
+
};
|
|
2672
|
+
this.slashCommandConfig = {
|
|
2673
|
+
triggerChar: this.commandTriggerChar,
|
|
2674
|
+
dropUp: true,
|
|
2675
|
+
labelKey: 'name',
|
|
2442
2676
|
returnTrigger: true,
|
|
2443
2677
|
mentionFilter: (searchString, items) => this.filter(searchString, items),
|
|
2444
2678
|
mentionSelect: (item, triggerChar) => this.itemSelectedFromAutocompleteList(item, triggerChar),
|
|
@@ -2451,20 +2685,30 @@ class AutocompleteTextareaComponent {
|
|
|
2451
2685
|
void this.updateMentionOptions(searchTerm);
|
|
2452
2686
|
}
|
|
2453
2687
|
});
|
|
2454
|
-
this.subscriptions.push(this.channelService.activeChannel$.subscribe(() => {
|
|
2688
|
+
this.subscriptions.push(this.channelService.activeChannel$.subscribe((channel) => {
|
|
2689
|
+
var _a;
|
|
2690
|
+
const commands = ((_a = channel === null || channel === void 0 ? void 0 : channel.getConfig()) === null || _a === void 0 ? void 0 : _a.commands) || [];
|
|
2691
|
+
this.slashCommandConfig.items = commands.map((c) => (Object.assign(Object.assign({}, c), { [this.autocompleteKey]: c.name, type: 'command' })));
|
|
2455
2692
|
this.mentionedUsers = [];
|
|
2456
2693
|
this.userMentions.next([...this.mentionedUsers]);
|
|
2457
2694
|
void this.updateMentionOptions(this.searchTerm$.getValue());
|
|
2458
2695
|
}));
|
|
2696
|
+
this.autocompleteConfig.mentions = [
|
|
2697
|
+
this.userMentionConfig,
|
|
2698
|
+
this.slashCommandConfig,
|
|
2699
|
+
];
|
|
2459
2700
|
}
|
|
2460
2701
|
ngOnChanges(changes) {
|
|
2461
2702
|
if (changes.areMentionsEnabled) {
|
|
2462
2703
|
if (this.areMentionsEnabled) {
|
|
2463
|
-
this.autocompleteConfig.mentions = [
|
|
2704
|
+
this.autocompleteConfig.mentions = [
|
|
2705
|
+
this.userMentionConfig,
|
|
2706
|
+
this.slashCommandConfig,
|
|
2707
|
+
];
|
|
2464
2708
|
this.autocompleteConfig = Object.assign({}, this.autocompleteConfig);
|
|
2465
2709
|
}
|
|
2466
2710
|
else {
|
|
2467
|
-
this.autocompleteConfig.mentions = [];
|
|
2711
|
+
this.autocompleteConfig.mentions = [this.slashCommandConfig];
|
|
2468
2712
|
this.autocompleteConfig = Object.assign({}, this.autocompleteConfig);
|
|
2469
2713
|
}
|
|
2470
2714
|
}
|
|
@@ -2480,7 +2724,9 @@ class AutocompleteTextareaComponent {
|
|
|
2480
2724
|
this.mentionedUsers.push((item.user ? item.user : item));
|
|
2481
2725
|
this.userMentions.next([...this.mentionedUsers]);
|
|
2482
2726
|
}
|
|
2483
|
-
return triggerChar +
|
|
2727
|
+
return (triggerChar +
|
|
2728
|
+
item.autocompleteLabel +
|
|
2729
|
+
(triggerChar === this.commandTriggerChar ? ' ' : ''));
|
|
2484
2730
|
}
|
|
2485
2731
|
autcompleteSearchTermChanged(searchTerm) {
|
|
2486
2732
|
if (searchTerm === this.mentionTriggerChar) {
|
|
@@ -2524,7 +2770,10 @@ class AutocompleteTextareaComponent {
|
|
|
2524
2770
|
return Object.assign(Object.assign({}, i), { autocompleteLabel: user.name || user.id, type: 'mention' });
|
|
2525
2771
|
}));
|
|
2526
2772
|
this.userMentionConfig.items = items;
|
|
2527
|
-
this.autocompleteConfig.mentions = [
|
|
2773
|
+
this.autocompleteConfig.mentions = [
|
|
2774
|
+
this.userMentionConfig,
|
|
2775
|
+
this.slashCommandConfig,
|
|
2776
|
+
];
|
|
2528
2777
|
this.autocompleteConfig = Object.assign({}, this.autocompleteConfig);
|
|
2529
2778
|
});
|
|
2530
2779
|
}
|
|
@@ -2543,7 +2792,7 @@ class AutocompleteTextareaComponent {
|
|
|
2543
2792
|
}
|
|
2544
2793
|
}
|
|
2545
2794
|
AutocompleteTextareaComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: AutocompleteTextareaComponent, deps: [{ token: ChannelService }, { token: ChatClientService }, { token: TransliterationService }], target: i0.ɵɵFactoryTarget.Component });
|
|
2546
|
-
AutocompleteTextareaComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.5", type: AutocompleteTextareaComponent, selector: "stream-autocomplete-textarea", inputs: { value: "value", areMentionsEnabled: "areMentionsEnabled", mentionAutocompleteItemTemplate: "mentionAutocompleteItemTemplate", mentionScope: "mentionScope" }, outputs: { valueChange: "valueChange", send: "send", userMentions: "userMentions" }, host: { properties: { "class": "this.class" } }, viewQueries: [{ propertyName: "messageInput", first: true, predicate: ["input"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<textarea\n [value]=\"value || ''\"\n autofocus\n data-testid=\"textarea\"\n #input\n placeholder=\"{{ 'streamChat.Type your message' | translate }}\"\n class=\"rta__textarea str-chat__textarea__textarea\"\n rows=\"1\"\n (input)=\"inputChanged()\"\n (keydown.enter)=\"sent($event)\"\n [mentionConfig]=\"autocompleteConfig\"\n (searchTerm)=\"autcompleteSearchTermChanged($event)\"\n [mentionListTemplate]=\"autocompleteItem\"\n (blur)=\"inputLeft()\"\n></textarea>\n<ng-template #autocompleteItem let-item=\"item\">\n <div class=\"rta rta__item str-chat__emojisearch__item\" [ngSwitch]=\"item.type\">\n <div class=\"rta__entity\" *ngSwitchCase=\"'mention'\">\n <ng-container\n *ngTemplateOutlet=\"\n mentionAutocompleteItemTemplate || defaultMentionTemplate;\n context: { item: item }\n \"\n ></ng-container>\n </div>\n </div>\n</ng-template>\n\n<ng-template #defaultMentionTemplate let-item=\"item\">\n <div class=\"str-chat__user-item\">\n <stream-avatar\n data-testclass=\"avatar\"\n class=\"str-chat__avatar str-chat__avatar--circle\"\n style=\"height: 20px\"\n [size]=\"20\"\n [imageUrl]=\"item.image || item.user?.image\"\n [name]=\"item.autocompleteLabel\"\n ></stream-avatar>\n <span data-testclass=\"username\" class=\"str-chat__user-item--name\">{{\n item.autocompleteLabel\n }}</span>\n </div>\n</ng-template>\n", components: [{ type: AvatarComponent, selector: "stream-avatar", inputs: ["name", "imageUrl", "size"] }], directives: [{ type: i5.MentionDirective, selector: "[mention], [mentionConfig]", inputs: ["mentionConfig", "mention", "mentionListTemplate"], outputs: ["searchTerm", "itemSelected", "opened", "closed"] }, { type:
|
|
2795
|
+
AutocompleteTextareaComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.5", type: AutocompleteTextareaComponent, selector: "stream-autocomplete-textarea", inputs: { value: "value", areMentionsEnabled: "areMentionsEnabled", mentionAutocompleteItemTemplate: "mentionAutocompleteItemTemplate", commandAutocompleteItemTemplate: "commandAutocompleteItemTemplate", mentionScope: "mentionScope" }, outputs: { valueChange: "valueChange", send: "send", userMentions: "userMentions" }, host: { properties: { "class": "this.class" } }, viewQueries: [{ propertyName: "messageInput", first: true, predicate: ["input"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<textarea\n [value]=\"value || ''\"\n autofocus\n data-testid=\"textarea\"\n #input\n placeholder=\"{{ 'streamChat.Type your message' | translate }}\"\n class=\"rta__textarea str-chat__textarea__textarea\"\n rows=\"1\"\n (input)=\"inputChanged()\"\n (keydown.enter)=\"sent($event)\"\n [mentionConfig]=\"autocompleteConfig\"\n (searchTerm)=\"autcompleteSearchTermChanged($event)\"\n [mentionListTemplate]=\"autocompleteItem\"\n (blur)=\"inputLeft()\"\n></textarea>\n<ng-template #autocompleteItem let-item=\"item\">\n <div class=\"rta rta__item str-chat__emojisearch__item\" [ngSwitch]=\"item.type\">\n <div class=\"rta__entity\" *ngSwitchCase=\"'mention'\">\n <ng-container\n *ngTemplateOutlet=\"\n mentionAutocompleteItemTemplate || defaultMentionTemplate;\n context: { item: item }\n \"\n ></ng-container>\n </div>\n <div class=\"rta__entity\" *ngSwitchCase=\"'command'\">\n <ng-container\n *ngTemplateOutlet=\"\n commandAutocompleteItemTemplate || defaultCommandTemplate;\n context: { item: item }\n \"\n ></ng-container>\n </div>\n </div>\n</ng-template>\n\n<ng-template #defaultCommandTemplate let-item=\"item\">\n <div class=\"str-chat__slash-command\">\n <span class=\"str-chat__slash-command-header\">\n <strong data-testclass=\"command-name\">{{ item.name }}</strong>\n {{ item.args }}\n </span>\n <br />\n <span class=\"str-chat__slash-command-description\">{{\n item.description\n }}</span>\n </div>\n</ng-template>\n\n<ng-template #defaultMentionTemplate let-item=\"item\">\n <div class=\"str-chat__user-item\">\n <stream-avatar\n data-testclass=\"avatar\"\n class=\"str-chat__avatar str-chat__avatar--circle\"\n style=\"height: 20px\"\n [size]=\"20\"\n [imageUrl]=\"item.image || item.user?.image\"\n [name]=\"item.autocompleteLabel\"\n ></stream-avatar>\n <span data-testclass=\"username\" class=\"str-chat__user-item--name\">{{\n item.autocompleteLabel\n }}</span>\n </div>\n</ng-template>\n", components: [{ type: AvatarComponent, selector: "stream-avatar", inputs: ["name", "imageUrl", "size"] }], directives: [{ type: i5.MentionDirective, selector: "[mention], [mentionConfig]", inputs: ["mentionConfig", "mention", "mentionListTemplate"], outputs: ["searchTerm", "itemSelected", "opened", "closed"] }, { type: i6.NgSwitch, selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { type: i6.NgSwitchCase, selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }, { type: i6.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet"] }], pipes: { "translate": i10.TranslatePipe } });
|
|
2547
2796
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: AutocompleteTextareaComponent, decorators: [{
|
|
2548
2797
|
type: Component,
|
|
2549
2798
|
args: [{
|
|
@@ -2559,6 +2808,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImpor
|
|
|
2559
2808
|
type: Input
|
|
2560
2809
|
}], mentionAutocompleteItemTemplate: [{
|
|
2561
2810
|
type: Input
|
|
2811
|
+
}], commandAutocompleteItemTemplate: [{
|
|
2812
|
+
type: Input
|
|
2562
2813
|
}], mentionScope: [{
|
|
2563
2814
|
type: Input
|
|
2564
2815
|
}], valueChange: [{
|
|
@@ -2617,30 +2868,37 @@ class MessageListComponent {
|
|
|
2617
2868
|
this.channelService = channelService;
|
|
2618
2869
|
this.chatClientService = chatClientService;
|
|
2619
2870
|
this.imageLoadService = imageLoadService;
|
|
2620
|
-
|
|
2871
|
+
/**
|
|
2872
|
+
* @deprecated https://getstream.io/chat/docs/sdk/angular/components/message_list/#caution-arereactionsenabled-deprecated
|
|
2873
|
+
*/
|
|
2874
|
+
this.areReactionsEnabled = undefined;
|
|
2875
|
+
/**
|
|
2876
|
+
* @deprecated https://getstream.io/chat/docs/sdk/angular/components/message_list/#caution-enabledmessageactions-deprecated
|
|
2877
|
+
*/
|
|
2621
2878
|
/* eslint-disable-next-line @angular-eslint/no-input-rename */
|
|
2622
|
-
this.enabledMessageActionsInput =
|
|
2879
|
+
this.enabledMessageActionsInput = undefined;
|
|
2880
|
+
this.mode = 'main';
|
|
2623
2881
|
this.enabledMessageActions = [];
|
|
2624
2882
|
this.class = 'str-chat-angular__main-panel-inner str-chat-angular__message-list-host';
|
|
2625
2883
|
this.unreadMessageCount = 0;
|
|
2626
2884
|
this.groupStyles = [];
|
|
2627
2885
|
this.authorizedMessageActions = ['flag'];
|
|
2628
2886
|
this.isUserScrolledUpThreshold = 300;
|
|
2629
|
-
this.
|
|
2887
|
+
this.subscriptions = [];
|
|
2888
|
+
this.subscriptions.push(this.channelService.activeChannel$.subscribe((channel) => {
|
|
2630
2889
|
var _a;
|
|
2631
|
-
this.
|
|
2632
|
-
this.hasNewMessages = true;
|
|
2633
|
-
this.isUserScrolledUp = false;
|
|
2634
|
-
this.containerHeight = undefined;
|
|
2635
|
-
this.olderMassagesLoaded = false;
|
|
2636
|
-
this.oldestMessageDate = undefined;
|
|
2637
|
-
this.unreadMessageCount = 0;
|
|
2638
|
-
this.isNewMessageSentByUser = undefined;
|
|
2890
|
+
this.resetScrollState();
|
|
2639
2891
|
const capabilites = (_a = channel === null || channel === void 0 ? void 0 : channel.data) === null || _a === void 0 ? void 0 : _a.own_capabilities;
|
|
2640
2892
|
if (capabilites) {
|
|
2641
2893
|
this.canReactToMessage = capabilites.indexOf('send-reaction') !== -1;
|
|
2642
2894
|
this.canReceiveReadEvents = capabilites.indexOf('read-events') !== -1;
|
|
2643
2895
|
this.authorizedMessageActions = [];
|
|
2896
|
+
if (this.canReactToMessage) {
|
|
2897
|
+
this.authorizedMessageActions.push('send-reaction');
|
|
2898
|
+
}
|
|
2899
|
+
if (this.canReceiveReadEvents) {
|
|
2900
|
+
this.authorizedMessageActions.push('read-events');
|
|
2901
|
+
}
|
|
2644
2902
|
if (capabilites.indexOf('flag-message') !== -1) {
|
|
2645
2903
|
this.authorizedMessageActions.push('flag');
|
|
2646
2904
|
}
|
|
@@ -2658,47 +2916,13 @@ class MessageListComponent {
|
|
|
2658
2916
|
this.authorizedMessageActions.push('delete');
|
|
2659
2917
|
this.authorizedMessageActions.push('delete-any');
|
|
2660
2918
|
}
|
|
2661
|
-
|
|
2662
|
-
|
|
2663
|
-
});
|
|
2664
|
-
this.messages$ = this.channelService.activeChannelMessages$.pipe(tap((messages) => {
|
|
2665
|
-
var _a, _b, _c, _d, _e;
|
|
2666
|
-
if (messages.length === 0) {
|
|
2667
|
-
return;
|
|
2668
|
-
}
|
|
2669
|
-
const currentLatestMessageDate = messages[messages.length - 1].created_at;
|
|
2670
|
-
if (!this.latestMessageDate ||
|
|
2671
|
-
((_a = this.latestMessageDate) === null || _a === void 0 ? void 0 : _a.getTime()) < currentLatestMessageDate.getTime()) {
|
|
2672
|
-
this.latestMessageDate = currentLatestMessageDate;
|
|
2673
|
-
this.hasNewMessages = true;
|
|
2674
|
-
this.isNewMessageSentByUser =
|
|
2675
|
-
((_b = messages[messages.length - 1].user) === null || _b === void 0 ? void 0 : _b.id) ===
|
|
2676
|
-
((_d = (_c = this.chatClientService.chatClient) === null || _c === void 0 ? void 0 : _c.user) === null || _d === void 0 ? void 0 : _d.id);
|
|
2677
|
-
if (this.isUserScrolledUp) {
|
|
2678
|
-
this.unreadMessageCount++;
|
|
2919
|
+
if (capabilites.indexOf('send-reply') !== -1) {
|
|
2920
|
+
this.authorizedMessageActions.push('send-reply');
|
|
2679
2921
|
}
|
|
2922
|
+
this.setEnabledActions();
|
|
2680
2923
|
}
|
|
2681
|
-
const currentOldestMessageDate = messages[0].created_at;
|
|
2682
|
-
if (!this.oldestMessageDate) {
|
|
2683
|
-
this.oldestMessageDate = currentOldestMessageDate;
|
|
2684
|
-
}
|
|
2685
|
-
else if (((_e = this.oldestMessageDate) === null || _e === void 0 ? void 0 : _e.getTime()) > currentOldestMessageDate.getTime()) {
|
|
2686
|
-
this.oldestMessageDate = currentOldestMessageDate;
|
|
2687
|
-
this.olderMassagesLoaded = true;
|
|
2688
|
-
}
|
|
2689
|
-
}), tap((messages) => {
|
|
2690
|
-
this.groupStyles = messages.map((m, i) => getGroupStyles(m, messages[i - 1], messages[i + 1]));
|
|
2691
|
-
}), tap((messages) => {
|
|
2692
|
-
var _a;
|
|
2693
|
-
return (this.lastSentMessageId = (_a = [...messages]
|
|
2694
|
-
.reverse()
|
|
2695
|
-
.find((m) => {
|
|
2696
|
-
var _a, _b, _c;
|
|
2697
|
-
return ((_a = m.user) === null || _a === void 0 ? void 0 : _a.id) === ((_c = (_b = this.chatClientService.chatClient) === null || _b === void 0 ? void 0 : _b.user) === null || _c === void 0 ? void 0 : _c.id) &&
|
|
2698
|
-
m.status !== 'sending';
|
|
2699
|
-
})) === null || _a === void 0 ? void 0 : _a.id);
|
|
2700
2924
|
}));
|
|
2701
|
-
this.imageLoadService.imageLoad$.subscribe(() => {
|
|
2925
|
+
this.subscriptions.push(this.imageLoadService.imageLoad$.subscribe(() => {
|
|
2702
2926
|
if (!this.isUserScrolledUp) {
|
|
2703
2927
|
this.scrollToBottom();
|
|
2704
2928
|
// Hacky and unreliable workaround to scroll down after loaded images move the scrollbar
|
|
@@ -2706,12 +2930,27 @@ class MessageListComponent {
|
|
|
2706
2930
|
this.scrollToBottom();
|
|
2707
2931
|
}, 300);
|
|
2708
2932
|
}
|
|
2709
|
-
});
|
|
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$();
|
|
2710
2946
|
}
|
|
2711
2947
|
ngOnChanges(changes) {
|
|
2712
2948
|
if (changes.enabledMessageActionsInput) {
|
|
2713
2949
|
this.setEnabledActions();
|
|
2714
2950
|
}
|
|
2951
|
+
if (changes.mode) {
|
|
2952
|
+
this.setMessages$();
|
|
2953
|
+
}
|
|
2715
2954
|
}
|
|
2716
2955
|
ngAfterViewChecked() {
|
|
2717
2956
|
if (this.hasNewMessages) {
|
|
@@ -2730,6 +2969,15 @@ class MessageListComponent {
|
|
|
2730
2969
|
this.containerHeight = this.scrollContainer.nativeElement.scrollHeight;
|
|
2731
2970
|
this.olderMassagesLoaded = false;
|
|
2732
2971
|
}
|
|
2972
|
+
else if (this.containerHeight !== undefined &&
|
|
2973
|
+
this.containerHeight < this.scrollContainer.nativeElement.scrollHeight &&
|
|
2974
|
+
!this.isUserScrolledUp) {
|
|
2975
|
+
this.scrollToBottom();
|
|
2976
|
+
this.containerHeight = this.scrollContainer.nativeElement.scrollHeight;
|
|
2977
|
+
}
|
|
2978
|
+
}
|
|
2979
|
+
ngOnDestroy() {
|
|
2980
|
+
this.subscriptions.forEach((s) => s.unsubscribe());
|
|
2733
2981
|
}
|
|
2734
2982
|
trackByMessageId(index, item) {
|
|
2735
2983
|
return item.id;
|
|
@@ -2739,6 +2987,7 @@ class MessageListComponent {
|
|
|
2739
2987
|
this.scrollContainer.nativeElement.scrollHeight;
|
|
2740
2988
|
}
|
|
2741
2989
|
scrolled() {
|
|
2990
|
+
var _a, _b;
|
|
2742
2991
|
this.isUserScrolledUp =
|
|
2743
2992
|
this.scrollContainer.nativeElement.scrollHeight -
|
|
2744
2993
|
(this.scrollContainer.nativeElement.scrollTop +
|
|
@@ -2747,20 +2996,35 @@ class MessageListComponent {
|
|
|
2747
2996
|
if (!this.isUserScrolledUp) {
|
|
2748
2997
|
this.unreadMessageCount = 0;
|
|
2749
2998
|
}
|
|
2750
|
-
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))) {
|
|
2751
3004
|
this.containerHeight = this.scrollContainer.nativeElement.scrollHeight;
|
|
2752
|
-
|
|
3005
|
+
this.mode === 'main'
|
|
3006
|
+
? void this.channelService.loadMoreMessages()
|
|
3007
|
+
: void this.channelService.loadMoreThreadReplies();
|
|
2753
3008
|
}
|
|
3009
|
+
this.prevScrollTop = this.scrollContainer.nativeElement.scrollTop;
|
|
2754
3010
|
}
|
|
2755
3011
|
preserveScrollbarPosition() {
|
|
2756
3012
|
this.scrollContainer.nativeElement.scrollTop =
|
|
2757
|
-
this.
|
|
3013
|
+
(this.prevScrollTop || 0) +
|
|
3014
|
+
(this.scrollContainer.nativeElement.scrollHeight - this.containerHeight);
|
|
2758
3015
|
}
|
|
2759
3016
|
setEnabledActions() {
|
|
2760
3017
|
this.enabledMessageActions = [];
|
|
2761
3018
|
if (!this.enabledMessageActionsInput) {
|
|
3019
|
+
this.enabledMessageActions = this.authorizedMessageActions;
|
|
2762
3020
|
return;
|
|
2763
3021
|
}
|
|
3022
|
+
this.enabledMessageActionsInput = [
|
|
3023
|
+
...this.enabledMessageActionsInput,
|
|
3024
|
+
'send-reaction',
|
|
3025
|
+
'read-events',
|
|
3026
|
+
'send-reply',
|
|
3027
|
+
];
|
|
2764
3028
|
this.enabledMessageActionsInput.forEach((action) => {
|
|
2765
3029
|
const isAuthorized = this.authorizedMessageActions.indexOf(action) !== -1;
|
|
2766
3030
|
if (isAuthorized) {
|
|
@@ -2768,9 +3032,61 @@ class MessageListComponent {
|
|
|
2768
3032
|
}
|
|
2769
3033
|
});
|
|
2770
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
|
+
}
|
|
2771
3087
|
}
|
|
2772
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 });
|
|
2773
|
-
MessageListComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.5", type: MessageListComponent, selector: "stream-message-list", inputs: { messageTemplate: "messageTemplate", messageInputTemplate: "messageInputTemplate", mentionTemplate: "mentionTemplate", areReactionsEnabled: "areReactionsEnabled", enabledMessageActionsInput: ["enabledMessageActions", "enabledMessageActionsInput"] }, host: { properties: { "class": "this.class" } }, viewQueries: [{ propertyName: "scrollContainer", first: true, predicate: ["scrollContainer"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div\n #scrollContainer\n data-testid=\"scroll-container\"\n class=\"str-chat__list\"\n (scroll)=\"scrolled()\"\n>\n <div class=\"str-chat__reverse-infinite-scroll\">\n <ul class=\"str-chat__ul\">\n <li\n data-testclass=\"message\"\n *ngFor=\"\n let message of messages$ | async;\n let i = index;\n trackBy: trackByMessageId\n \"\n class=\"str-chat__li str-chat__li--{{ groupStyles[i] }}\"\n >\n <ng-container
|
|
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 } });
|
|
2774
3090
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: MessageListComponent, decorators: [{
|
|
2775
3091
|
type: Component,
|
|
2776
3092
|
args: [{
|
|
@@ -2789,12 +3105,49 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImpor
|
|
|
2789
3105
|
}], enabledMessageActionsInput: [{
|
|
2790
3106
|
type: Input,
|
|
2791
3107
|
args: ['enabledMessageActions']
|
|
3108
|
+
}], mode: [{
|
|
3109
|
+
type: Input
|
|
2792
3110
|
}], class: [{
|
|
2793
3111
|
type: HostBinding,
|
|
2794
3112
|
args: ['class']
|
|
2795
3113
|
}], scrollContainer: [{
|
|
2796
3114
|
type: ViewChild,
|
|
2797
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']
|
|
2798
3151
|
}] } });
|
|
2799
3152
|
|
|
2800
3153
|
class StreamAvatarModule {
|
|
@@ -2830,7 +3183,8 @@ StreamChatModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "12.0.0", versio
|
|
|
2830
3183
|
NotificationListComponent,
|
|
2831
3184
|
AttachmentPreviewListComponent,
|
|
2832
3185
|
ModalComponent,
|
|
2833
|
-
TextareaDirective
|
|
3186
|
+
TextareaDirective,
|
|
3187
|
+
ThreadComponent], imports: [CommonModule, TranslateModule, StreamAvatarModule], exports: [ChannelComponent,
|
|
2834
3188
|
ChannelHeaderComponent,
|
|
2835
3189
|
ChannelListComponent,
|
|
2836
3190
|
ChannelPreviewComponent,
|
|
@@ -2846,7 +3200,8 @@ StreamChatModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "12.0.0", versio
|
|
|
2846
3200
|
NotificationListComponent,
|
|
2847
3201
|
AttachmentPreviewListComponent,
|
|
2848
3202
|
ModalComponent,
|
|
2849
|
-
StreamAvatarModule
|
|
3203
|
+
StreamAvatarModule,
|
|
3204
|
+
ThreadComponent] });
|
|
2850
3205
|
StreamChatModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: StreamChatModule, imports: [[CommonModule, TranslateModule, StreamAvatarModule], StreamAvatarModule] });
|
|
2851
3206
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImport: i0, type: StreamChatModule, decorators: [{
|
|
2852
3207
|
type: NgModule,
|
|
@@ -2869,6 +3224,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImpor
|
|
|
2869
3224
|
AttachmentPreviewListComponent,
|
|
2870
3225
|
ModalComponent,
|
|
2871
3226
|
TextareaDirective,
|
|
3227
|
+
ThreadComponent,
|
|
2872
3228
|
],
|
|
2873
3229
|
imports: [CommonModule, TranslateModule, StreamAvatarModule],
|
|
2874
3230
|
exports: [
|
|
@@ -2889,6 +3245,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImpor
|
|
|
2889
3245
|
AttachmentPreviewListComponent,
|
|
2890
3246
|
ModalComponent,
|
|
2891
3247
|
StreamAvatarModule,
|
|
3248
|
+
ThreadComponent,
|
|
2892
3249
|
],
|
|
2893
3250
|
}]
|
|
2894
3251
|
}] });
|
|
@@ -2951,5 +3308,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.5", ngImpor
|
|
|
2951
3308
|
* Generated bundle index. Do not edit.
|
|
2952
3309
|
*/
|
|
2953
3310
|
|
|
2954
|
-
export { AttachmentListComponent, AttachmentPreviewListComponent, AttachmentService, AutocompleteTextareaComponent, AvatarComponent, ChannelComponent, ChannelHeaderComponent, ChannelListComponent, ChannelListToggleService, ChannelPreviewComponent, ChannelService, ChatClientService, IconComponent, ImageLoadService, LoadingIndicatorComponent, MessageActionsBoxComponent, MessageComponent, MessageInputComponent, MessageInputConfigService, MessageListComponent, MessageReactionsComponent, ModalComponent, NotificationComponent, NotificationListComponent, NotificationService, StreamAutocompleteTextareaModule, StreamAvatarModule, StreamChatModule, StreamI18nService, StreamTextareaModule, TextareaComponent, TextareaDirective, ThemeService, TransliterationService, createMessagePreview, getDeviceWidth, getGroupStyles, getReadBy, getReadByText, isImageAttachment, isImageFile, parseDate, textareaInjectionToken };
|
|
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 };
|
|
2955
3312
|
//# sourceMappingURL=stream-chat-angular.js.map
|