stream-chat-angular 5.0.0 → 5.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/assets/version.d.ts +1 -1
- package/esm2020/assets/version.mjs +2 -2
- package/esm2020/lib/avatar/avatar.component.mjs +4 -1
- package/esm2020/lib/channel-list/channel-list.component.mjs +2 -2
- package/esm2020/lib/channel.service.mjs +9 -24
- package/esm2020/lib/message-actions.service.mjs +4 -4
- package/esm2020/lib/message-list/message-list.component.mjs +181 -249
- package/esm2020/lib/types.mjs +1 -1
- package/esm2020/lib/virtualized-list.service.mjs +271 -0
- package/esm2020/lib/virtualized-message-list.service.mjs +73 -0
- package/esm2020/lib/voice-recording/voice-recording.component.mjs +2 -2
- package/esm2020/public-api.mjs +3 -1
- package/fesm2015/stream-chat-angular.mjs +548 -284
- package/fesm2015/stream-chat-angular.mjs.map +1 -1
- package/fesm2020/stream-chat-angular.mjs +534 -273
- package/fesm2020/stream-chat-angular.mjs.map +1 -1
- package/lib/avatar/avatar.component.d.ts +3 -2
- package/lib/channel-list/channel-list.component.d.ts +1 -1
- package/lib/channel.service.d.ts +6 -12
- package/lib/message-list/message-list.component.d.ts +12 -18
- package/lib/types.d.ts +7 -0
- package/lib/virtualized-list.service.d.ts +58 -0
- package/lib/virtualized-message-list.service.d.ts +15 -0
- package/package.json +1 -1
- package/public-api.d.ts +2 -0
- package/src/assets/styles/css/index.css +1 -1
- package/src/assets/styles/css/index.layout.css +1 -1
- package/src/assets/styles/scss/LoadingIndicator/LoadingIndicator-layout.scss +16 -0
- package/src/assets/version.ts +1 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { __awaiter } from 'tslib';
|
|
2
2
|
import * as i0 from '@angular/core';
|
|
3
3
|
import { Injectable, Component, Input, EventEmitter, Output, ViewChild, HostBinding, ChangeDetectionStrategy, InjectionToken, Directive, Inject, NgModule } from '@angular/core';
|
|
4
|
-
import { BehaviorSubject, ReplaySubject, combineLatest, take as take$1, Subject, timer } from 'rxjs';
|
|
4
|
+
import { BehaviorSubject, ReplaySubject, combineLatest, take as take$1, Subject, timer, merge, switchMap, distinctUntilChanged, pairwise, filter as filter$1, of, map as map$1 } from 'rxjs';
|
|
5
5
|
import { StreamChat } from 'stream-chat';
|
|
6
6
|
import { take, shareReplay, map, first, filter, tap, debounceTime, throttleTime } from 'rxjs/operators';
|
|
7
7
|
import { v4 } from 'uuid';
|
|
@@ -20,7 +20,7 @@ import transliterate from '@stream-io/transliterate';
|
|
|
20
20
|
import * as i8$1 from 'angular-mentions';
|
|
21
21
|
import { MentionModule } from 'angular-mentions';
|
|
22
22
|
|
|
23
|
-
const version = '5.
|
|
23
|
+
const version = '5.1.0';
|
|
24
24
|
|
|
25
25
|
/**
|
|
26
26
|
* The `NotificationService` can be used to add or remove notifications. By default the [`NotificationList`](../components/NotificationListComponent.mdx) component displays the currently active notifications.
|
|
@@ -437,6 +437,7 @@ class ChannelService {
|
|
|
437
437
|
this.chatClientService = chatClientService;
|
|
438
438
|
this.ngZone = ngZone;
|
|
439
439
|
this.notificationService = notificationService;
|
|
440
|
+
this.messagePageSize = 25;
|
|
440
441
|
this.channelsSubject = new BehaviorSubject(undefined);
|
|
441
442
|
this.activeChannelSubject = new BehaviorSubject(undefined);
|
|
442
443
|
this.activeChannelMessagesSubject = new BehaviorSubject([]);
|
|
@@ -448,7 +449,6 @@ class ChannelService {
|
|
|
448
449
|
this.activeThreadMessagesSubject = new BehaviorSubject([]);
|
|
449
450
|
this.jumpToMessageSubject = new BehaviorSubject({ id: undefined, parentId: undefined });
|
|
450
451
|
this.latestMessageDateByUserByChannelsSubject = new BehaviorSubject({});
|
|
451
|
-
this.messagePageSize = 25;
|
|
452
452
|
this.attachmentMaxSizeFallbackInMB = 100;
|
|
453
453
|
this.messageToQuoteSubject = new BehaviorSubject(undefined);
|
|
454
454
|
this.usersTypingInChannelSubject = new BehaviorSubject([]);
|
|
@@ -556,23 +556,6 @@ class ChannelService {
|
|
|
556
556
|
.asObservable()
|
|
557
557
|
.pipe(shareReplay(1));
|
|
558
558
|
}
|
|
559
|
-
/**
|
|
560
|
-
* internal
|
|
561
|
-
*/
|
|
562
|
-
removeOldMessageFromMessageList() {
|
|
563
|
-
const channel = this.activeChannelSubject.getValue();
|
|
564
|
-
const channelMessages = channel === null || channel === void 0 ? void 0 : channel.state.latestMessages;
|
|
565
|
-
const targetLength = Math.ceil(ChannelService.MAX_MESSAGE_COUNT_IN_MESSAGE_LIST / 2);
|
|
566
|
-
if (!channel ||
|
|
567
|
-
!channelMessages ||
|
|
568
|
-
channelMessages !== (channel === null || channel === void 0 ? void 0 : channel.state.latestMessages) ||
|
|
569
|
-
channelMessages.length <= targetLength) {
|
|
570
|
-
return;
|
|
571
|
-
}
|
|
572
|
-
const messages = channelMessages;
|
|
573
|
-
messages.splice(0, messages.length - targetLength);
|
|
574
|
-
this.activeChannelMessagesSubject.next(messages);
|
|
575
|
-
}
|
|
576
559
|
/**
|
|
577
560
|
* If set to false, read events won't be sent as new messages are received. If set to true active channel (if any) will immediately be marked as read.
|
|
578
561
|
*/
|
|
@@ -1469,6 +1452,12 @@ class ChannelService {
|
|
|
1469
1452
|
get activeChannelMessages() {
|
|
1470
1453
|
return this.activeChannelMessagesSubject.getValue() || [];
|
|
1471
1454
|
}
|
|
1455
|
+
/**
|
|
1456
|
+
* The current thread replies
|
|
1457
|
+
*/
|
|
1458
|
+
get activeChannelThreadReplies() {
|
|
1459
|
+
return this.activeThreadMessagesSubject.getValue() || [];
|
|
1460
|
+
}
|
|
1472
1461
|
/**
|
|
1473
1462
|
* Get the last 1200 reactions of a message in the current active channel. If you need to fetch more reactions please use the [following endpoint](https://getstream.io/chat/docs/javascript/send_reaction/?language=javascript#paginating-reactions).
|
|
1474
1463
|
* @param messageId
|
|
@@ -1556,7 +1545,7 @@ class ChannelService {
|
|
|
1556
1545
|
return;
|
|
1557
1546
|
}
|
|
1558
1547
|
const messageIndex = messages.findIndex((m) => { var _a; return m.id === ((_a = event === null || event === void 0 ? void 0 : event.message) === null || _a === void 0 ? void 0 : _a.id); });
|
|
1559
|
-
if (messageIndex !== -1) {
|
|
1548
|
+
if (messageIndex !== -1 || event.type === 'message.deleted') {
|
|
1560
1549
|
isThreadReply
|
|
1561
1550
|
? this.activeThreadMessagesSubject.next([...messages])
|
|
1562
1551
|
: this.activeChannelMessagesSubject.next([...messages]);
|
|
@@ -1944,10 +1933,6 @@ class ChannelService {
|
|
|
1944
1933
|
});
|
|
1945
1934
|
}
|
|
1946
1935
|
}
|
|
1947
|
-
/**
|
|
1948
|
-
* @internal
|
|
1949
|
-
*/
|
|
1950
|
-
ChannelService.MAX_MESSAGE_COUNT_IN_MESSAGE_LIST = 250;
|
|
1951
1936
|
/**
|
|
1952
1937
|
* @internal
|
|
1953
1938
|
*/
|
|
@@ -2725,6 +2710,9 @@ class AvatarComponent {
|
|
|
2725
2710
|
this.setFallbackChannelImage();
|
|
2726
2711
|
}
|
|
2727
2712
|
}
|
|
2713
|
+
ngOnDestroy() {
|
|
2714
|
+
this.subscriptions.forEach((s) => s.unsubscribe());
|
|
2715
|
+
}
|
|
2728
2716
|
setFallbackChannelImage() {
|
|
2729
2717
|
if (this.type !== 'channel') {
|
|
2730
2718
|
this.fallbackChannelImage = undefined;
|
|
@@ -3204,7 +3192,7 @@ class MessageActionsService {
|
|
|
3204
3192
|
actionHandler: (message) => {
|
|
3205
3193
|
void this.channelService.markMessageUnread(message.id);
|
|
3206
3194
|
},
|
|
3207
|
-
isVisible: (enabledActions,
|
|
3195
|
+
isVisible: (enabledActions, _, message) => enabledActions.indexOf('read-events') !== -1 && !message.parent_id,
|
|
3208
3196
|
},
|
|
3209
3197
|
{
|
|
3210
3198
|
actionName: 'quote',
|
|
@@ -3220,7 +3208,7 @@ class MessageActionsService {
|
|
|
3220
3208
|
actionHandler: (message) => {
|
|
3221
3209
|
void this.channelService.setAsActiveParentMessage(message);
|
|
3222
3210
|
},
|
|
3223
|
-
isVisible: (enabledActions,
|
|
3211
|
+
isVisible: (enabledActions, _, message) => enabledActions.indexOf('send-reply') !== -1 && !message.parent_id,
|
|
3224
3212
|
},
|
|
3225
3213
|
{
|
|
3226
3214
|
actionName: 'pin',
|
|
@@ -3241,7 +3229,7 @@ class MessageActionsService {
|
|
|
3241
3229
|
yield this.chatClientService.flagMessage(message.id);
|
|
3242
3230
|
this.notificationService.addTemporaryNotification('streamChat.Message has been successfully flagged', 'success');
|
|
3243
3231
|
}
|
|
3244
|
-
catch (
|
|
3232
|
+
catch (error) {
|
|
3245
3233
|
this.notificationService.addTemporaryNotification('streamChat.Error adding flag');
|
|
3246
3234
|
}
|
|
3247
3235
|
}),
|
|
@@ -4158,7 +4146,7 @@ class ChannelListComponent {
|
|
|
4158
4146
|
this.isLoadingMoreChannels = false;
|
|
4159
4147
|
});
|
|
4160
4148
|
}
|
|
4161
|
-
trackByChannelId(
|
|
4149
|
+
trackByChannelId(_, item) {
|
|
4162
4150
|
return item.cid;
|
|
4163
4151
|
}
|
|
4164
4152
|
}
|
|
@@ -4408,7 +4396,7 @@ class VoiceRecordingComponent {
|
|
|
4408
4396
|
: this.audioElement.nativeElement.pause();
|
|
4409
4397
|
this.isError = false;
|
|
4410
4398
|
}
|
|
4411
|
-
catch (
|
|
4399
|
+
catch (error) {
|
|
4412
4400
|
this.isError = true;
|
|
4413
4401
|
}
|
|
4414
4402
|
});
|
|
@@ -6365,6 +6353,350 @@ const isOnSameDay = (date1, date2) => {
|
|
|
6365
6353
|
date1.getDate() === date2.getDate());
|
|
6366
6354
|
};
|
|
6367
6355
|
|
|
6356
|
+
/**
|
|
6357
|
+
* The `VirtualizedListService` removes items from a list that are not currently displayed. This is a high-level overview of how it works:
|
|
6358
|
+
* - Create a new instance for each list that needs virtualization
|
|
6359
|
+
* - Input: Provide a reactive stream that emits all items in the list
|
|
6360
|
+
* - Input: Provide a reactive stream that emit the current scroll position (top, middle or bottom)
|
|
6361
|
+
* - Input: maximum number of items that are allowed in the list (in practice the service can make the virtualized list half this number, you should take this into account when choosing the value)
|
|
6362
|
+
* - Output: The service will emit the current list of displayed items via the virtualized items reactive stream
|
|
6363
|
+
* - For simplicity, the service won't track the height of the items, nor it needs an exact scroll location -> this is how removing items work:
|
|
6364
|
+
* - If scroll location is bottom/top items around the current bottom/top item will be emitted in the virtualized items stream
|
|
6365
|
+
* - If scroll location is middle, the service won't remove items, if new items are received, those will be appended to the virtualized list (this means that in theory the list can grow very big if a lot of new items are received while the user is scrolled somewhere, this is a trade-off for the simplicity of no height tracking)
|
|
6366
|
+
* - Since there is no height tracking, you should make sure to provide a maximum number that is big enough to fill the biggest expected screen size twice
|
|
6367
|
+
* - If the user scrolls to the bottom/top and there are no more local items to show, the service will trigger a query to load more items
|
|
6368
|
+
* - Input: you should provide the page size to use, in order for the service to determine if loading is necessary
|
|
6369
|
+
*
|
|
6370
|
+
* The `VirtualizedMessageListService` provides an implementation for the message list component.
|
|
6371
|
+
*/
|
|
6372
|
+
class VirtualizedListService {
|
|
6373
|
+
constructor(allItems$, scrollPosition$, jumpToItem$, pageSize = 25, maxItemCount = pageSize * 4) {
|
|
6374
|
+
this.allItems$ = allItems$;
|
|
6375
|
+
this.scrollPosition$ = scrollPosition$;
|
|
6376
|
+
this.jumpToItem$ = jumpToItem$;
|
|
6377
|
+
this.pageSize = pageSize;
|
|
6378
|
+
this.maxItemCount = maxItemCount;
|
|
6379
|
+
this.queryStateSubject = new BehaviorSubject({
|
|
6380
|
+
state: 'success',
|
|
6381
|
+
});
|
|
6382
|
+
this.bufferOnTop = 0;
|
|
6383
|
+
this.bufferOnBottom = 0;
|
|
6384
|
+
this.loadFromBuffer$ = new Subject();
|
|
6385
|
+
this.virtualizedItemsSubject = new BehaviorSubject([]);
|
|
6386
|
+
this.subscriptions = [];
|
|
6387
|
+
this.virtualizedItems$ = this.virtualizedItemsSubject.asObservable();
|
|
6388
|
+
this.queryState$ = this.queryStateSubject.asObservable();
|
|
6389
|
+
this.subscriptions.push(this.virtualizedItems$.subscribe((virtaluzedItems) => {
|
|
6390
|
+
this.allItems$.pipe(take$1(1)).subscribe((allItems) => {
|
|
6391
|
+
if (virtaluzedItems.length === allItems.length) {
|
|
6392
|
+
this.bufferOnTop = 0;
|
|
6393
|
+
this.bufferOnBottom = 0;
|
|
6394
|
+
}
|
|
6395
|
+
else if (virtaluzedItems.length === 0) {
|
|
6396
|
+
this.bufferOnTop = allItems.length;
|
|
6397
|
+
this.bufferOnBottom = 0;
|
|
6398
|
+
}
|
|
6399
|
+
else {
|
|
6400
|
+
this.bufferOnTop = allItems.indexOf(virtaluzedItems[0]);
|
|
6401
|
+
this.bufferOnBottom =
|
|
6402
|
+
allItems.length -
|
|
6403
|
+
allItems.indexOf(virtaluzedItems[virtaluzedItems.length - 1]) -
|
|
6404
|
+
1;
|
|
6405
|
+
}
|
|
6406
|
+
});
|
|
6407
|
+
}));
|
|
6408
|
+
this.subscriptions.push(merge(this.allItems$, this.loadFromBuffer$)
|
|
6409
|
+
.pipe(switchMap(() => {
|
|
6410
|
+
return combineLatest([
|
|
6411
|
+
this.allItems$.pipe(take$1(1)),
|
|
6412
|
+
this.scrollPosition$.pipe(take$1(1)),
|
|
6413
|
+
]);
|
|
6414
|
+
}))
|
|
6415
|
+
.subscribe(([items, scrollPosition]) => {
|
|
6416
|
+
if (scrollPosition === 'middle') {
|
|
6417
|
+
return;
|
|
6418
|
+
}
|
|
6419
|
+
const currentItems = this.virtualizedItemsSubject.getValue();
|
|
6420
|
+
if (items.length <= this.maxItemCount) {
|
|
6421
|
+
this.virtualizedItemsSubject.next(items);
|
|
6422
|
+
}
|
|
6423
|
+
else {
|
|
6424
|
+
let startIndex = 0;
|
|
6425
|
+
let endIndex = undefined;
|
|
6426
|
+
const numberOfItemsToRemove = items.length - Math.round(this.maxItemCount / 2);
|
|
6427
|
+
const numberOfItemsAfterRemove = items.length - numberOfItemsToRemove;
|
|
6428
|
+
switch (scrollPosition) {
|
|
6429
|
+
case 'top':
|
|
6430
|
+
if (currentItems.length > 0) {
|
|
6431
|
+
const middleIndex = items.findIndex((i) => this.isEqual(i, currentItems[0]));
|
|
6432
|
+
if (middleIndex !== -1) {
|
|
6433
|
+
startIndex = Math.max(0, middleIndex - Math.ceil(numberOfItemsAfterRemove / 2));
|
|
6434
|
+
endIndex = startIndex + numberOfItemsAfterRemove;
|
|
6435
|
+
}
|
|
6436
|
+
}
|
|
6437
|
+
else {
|
|
6438
|
+
endIndex = numberOfItemsAfterRemove;
|
|
6439
|
+
}
|
|
6440
|
+
break;
|
|
6441
|
+
case 'bottom':
|
|
6442
|
+
if (currentItems.length > 0) {
|
|
6443
|
+
const middleIndex = items.findIndex((i) => this.isEqual(i, currentItems[currentItems.length - 1]));
|
|
6444
|
+
if (middleIndex !== -1) {
|
|
6445
|
+
endIndex = Math.min(items.length, middleIndex + Math.floor(numberOfItemsAfterRemove / 2) + 1);
|
|
6446
|
+
startIndex = endIndex - numberOfItemsAfterRemove;
|
|
6447
|
+
}
|
|
6448
|
+
}
|
|
6449
|
+
else {
|
|
6450
|
+
startIndex = items.length - numberOfItemsAfterRemove;
|
|
6451
|
+
}
|
|
6452
|
+
break;
|
|
6453
|
+
}
|
|
6454
|
+
const virtualizedItems = items.slice(startIndex, endIndex);
|
|
6455
|
+
this.virtualizedItemsSubject.next(virtualizedItems);
|
|
6456
|
+
}
|
|
6457
|
+
}));
|
|
6458
|
+
this.subscriptions.push(this.scrollPosition$
|
|
6459
|
+
.pipe(distinctUntilChanged())
|
|
6460
|
+
.subscribe((position) => {
|
|
6461
|
+
if (this.queryStateSubject.getValue().state === `loading-${position}`) {
|
|
6462
|
+
return;
|
|
6463
|
+
}
|
|
6464
|
+
if (position === 'top') {
|
|
6465
|
+
if (this.bufferOnTop < this.pageSize) {
|
|
6466
|
+
void this.loadMore(position);
|
|
6467
|
+
}
|
|
6468
|
+
else {
|
|
6469
|
+
this.loadMoreFromBuffer('top');
|
|
6470
|
+
}
|
|
6471
|
+
}
|
|
6472
|
+
else if (position === 'bottom') {
|
|
6473
|
+
if (this.bufferOnBottom < this.pageSize) {
|
|
6474
|
+
void this.loadMore(position);
|
|
6475
|
+
}
|
|
6476
|
+
else {
|
|
6477
|
+
this.loadMoreFromBuffer('bottom');
|
|
6478
|
+
}
|
|
6479
|
+
}
|
|
6480
|
+
}));
|
|
6481
|
+
this.subscriptions.push(this.allItems$
|
|
6482
|
+
.pipe(pairwise(), filter$1(() => {
|
|
6483
|
+
let scrollPosition;
|
|
6484
|
+
this.scrollPosition$
|
|
6485
|
+
.pipe(take$1(1))
|
|
6486
|
+
.subscribe((s) => (scrollPosition = s));
|
|
6487
|
+
return scrollPosition === 'middle';
|
|
6488
|
+
}))
|
|
6489
|
+
.subscribe(([prevItems, currentItems]) => {
|
|
6490
|
+
if (currentItems.length < this.maxItemCount ||
|
|
6491
|
+
this.virtualizedItems.length === 0) {
|
|
6492
|
+
this.virtualizedItemsSubject.next(currentItems);
|
|
6493
|
+
}
|
|
6494
|
+
else {
|
|
6495
|
+
const currentFirstItem = this.virtualizedItems[0];
|
|
6496
|
+
const currentLastItem = this.virtualizedItems[this.virtualizedItems.length - 1];
|
|
6497
|
+
const prevStartIndex = prevItems.findIndex((i) => this.isEqual(i, currentFirstItem));
|
|
6498
|
+
const prevEndIndex = prevItems.findIndex((i) => this.isEqual(i, currentLastItem));
|
|
6499
|
+
const isStartRemainedSame = currentItems[prevStartIndex]
|
|
6500
|
+
? this.isEqual(currentItems[prevStartIndex], currentFirstItem)
|
|
6501
|
+
: false;
|
|
6502
|
+
const isEndRemainedSame = currentItems[prevEndIndex]
|
|
6503
|
+
? this.isEqual(currentItems[prevEndIndex], currentLastItem)
|
|
6504
|
+
: false;
|
|
6505
|
+
const hasNewItemsBottom = prevEndIndex === prevItems.length - 1 && isEndRemainedSame
|
|
6506
|
+
? prevItems.length !== currentItems.length
|
|
6507
|
+
: false;
|
|
6508
|
+
if (isStartRemainedSame && isEndRemainedSame) {
|
|
6509
|
+
const endIndex = hasNewItemsBottom ? undefined : prevEndIndex + 1;
|
|
6510
|
+
this.virtualizedItemsSubject.next(currentItems.slice(prevStartIndex, endIndex));
|
|
6511
|
+
}
|
|
6512
|
+
let currentStartIndex = isStartRemainedSame ? prevStartIndex : -1;
|
|
6513
|
+
let currentEndIndex = isEndRemainedSame ? prevEndIndex : -1;
|
|
6514
|
+
if (!isStartRemainedSame) {
|
|
6515
|
+
currentStartIndex = currentItems.findIndex((i) => this.isEqual(i, currentFirstItem));
|
|
6516
|
+
}
|
|
6517
|
+
if (!isEndRemainedSame) {
|
|
6518
|
+
currentEndIndex = currentItems.findIndex((i) => this.isEqual(i, currentLastItem));
|
|
6519
|
+
}
|
|
6520
|
+
const hasNewItemsTop = prevStartIndex === 0 && !isStartRemainedSame
|
|
6521
|
+
? currentStartIndex !== 0
|
|
6522
|
+
: false;
|
|
6523
|
+
if (currentStartIndex !== -1 && currentEndIndex !== -1) {
|
|
6524
|
+
const startIndex = hasNewItemsTop ? 0 : currentStartIndex;
|
|
6525
|
+
this.virtualizedItemsSubject.next(currentItems.slice(startIndex, currentEndIndex + 1));
|
|
6526
|
+
}
|
|
6527
|
+
else {
|
|
6528
|
+
if (currentStartIndex === -1 && currentEndIndex !== -1) {
|
|
6529
|
+
currentStartIndex = Math.max(0, currentEndIndex - (prevEndIndex - prevStartIndex));
|
|
6530
|
+
}
|
|
6531
|
+
if (currentEndIndex === -1 && currentStartIndex !== -1) {
|
|
6532
|
+
currentEndIndex = Math.min(currentItems.length - 1, currentStartIndex + (prevEndIndex - prevStartIndex));
|
|
6533
|
+
}
|
|
6534
|
+
this.virtualizedItemsSubject.next(currentItems.slice(currentStartIndex, currentEndIndex + 1));
|
|
6535
|
+
}
|
|
6536
|
+
}
|
|
6537
|
+
}));
|
|
6538
|
+
if (this.jumpToItem$) {
|
|
6539
|
+
this.subscriptions.push(this.jumpToItem$
|
|
6540
|
+
.pipe(switchMap((jumpToItem) => combineLatest([this.allItems$.pipe(take$1(1)), of(jumpToItem)])))
|
|
6541
|
+
.subscribe(([allItems, jumpToItem]) => {
|
|
6542
|
+
if (jumpToItem.item) {
|
|
6543
|
+
if (allItems.length < this.maxItemCount) {
|
|
6544
|
+
this.virtualizedItemsSubject.next(allItems);
|
|
6545
|
+
}
|
|
6546
|
+
else {
|
|
6547
|
+
const itemIndex = allItems.findIndex((i) =>
|
|
6548
|
+
// @ts-expect-error TODO: do we know a better typing here?
|
|
6549
|
+
this.isEqual(i, jumpToItem.item));
|
|
6550
|
+
if (itemIndex === -1) {
|
|
6551
|
+
return;
|
|
6552
|
+
}
|
|
6553
|
+
else {
|
|
6554
|
+
const position = jumpToItem.position || 'middle';
|
|
6555
|
+
const numberOfItemsToRemove = allItems.length - Math.round(this.maxItemCount / 2);
|
|
6556
|
+
const numberOfItemsAfterRemove = allItems.length - numberOfItemsToRemove;
|
|
6557
|
+
let startIndex = -1;
|
|
6558
|
+
let endIndex = -1;
|
|
6559
|
+
switch (position) {
|
|
6560
|
+
case 'top':
|
|
6561
|
+
startIndex = itemIndex;
|
|
6562
|
+
endIndex = Math.min(allItems.length, startIndex + numberOfItemsAfterRemove);
|
|
6563
|
+
break;
|
|
6564
|
+
case 'bottom':
|
|
6565
|
+
endIndex = itemIndex + 1;
|
|
6566
|
+
startIndex = Math.max(0, endIndex - numberOfItemsAfterRemove);
|
|
6567
|
+
break;
|
|
6568
|
+
case 'middle': {
|
|
6569
|
+
const itemsOnTop = itemIndex;
|
|
6570
|
+
const itemsOnBottom = allItems.length - itemIndex;
|
|
6571
|
+
if (itemsOnTop < Math.ceil(numberOfItemsAfterRemove / 2)) {
|
|
6572
|
+
startIndex = 0;
|
|
6573
|
+
}
|
|
6574
|
+
if (itemsOnBottom <
|
|
6575
|
+
Math.floor(numberOfItemsAfterRemove / 2) + 1) {
|
|
6576
|
+
endIndex = allItems.length;
|
|
6577
|
+
}
|
|
6578
|
+
if (startIndex === -1) {
|
|
6579
|
+
if (endIndex !== -1) {
|
|
6580
|
+
startIndex = endIndex - numberOfItemsAfterRemove;
|
|
6581
|
+
}
|
|
6582
|
+
else {
|
|
6583
|
+
startIndex =
|
|
6584
|
+
itemIndex - Math.ceil(numberOfItemsAfterRemove / 2);
|
|
6585
|
+
}
|
|
6586
|
+
}
|
|
6587
|
+
if (endIndex === -1) {
|
|
6588
|
+
endIndex = startIndex + numberOfItemsAfterRemove;
|
|
6589
|
+
}
|
|
6590
|
+
}
|
|
6591
|
+
}
|
|
6592
|
+
this.virtualizedItemsSubject.next(allItems.slice(startIndex, endIndex));
|
|
6593
|
+
}
|
|
6594
|
+
}
|
|
6595
|
+
}
|
|
6596
|
+
}));
|
|
6597
|
+
}
|
|
6598
|
+
}
|
|
6599
|
+
/**
|
|
6600
|
+
* The current value of virtualized items
|
|
6601
|
+
*/
|
|
6602
|
+
get virtualizedItems() {
|
|
6603
|
+
return this.virtualizedItemsSubject.getValue();
|
|
6604
|
+
}
|
|
6605
|
+
/**
|
|
6606
|
+
* Remove all subscriptions, call this once you're done using an instance of this service
|
|
6607
|
+
*/
|
|
6608
|
+
dispose() {
|
|
6609
|
+
this.subscriptions.forEach((s) => s.unsubscribe());
|
|
6610
|
+
}
|
|
6611
|
+
loadMoreFromBuffer(_) {
|
|
6612
|
+
this.loadFromBuffer$.next();
|
|
6613
|
+
}
|
|
6614
|
+
loadMore(direction) {
|
|
6615
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
6616
|
+
this.queryStateSubject.next({ state: `loading-${direction}` });
|
|
6617
|
+
try {
|
|
6618
|
+
yield this.query(direction);
|
|
6619
|
+
this.queryStateSubject.next({ state: 'success' });
|
|
6620
|
+
}
|
|
6621
|
+
catch (e) {
|
|
6622
|
+
this.queryStateSubject.next({ state: 'error', error: e });
|
|
6623
|
+
}
|
|
6624
|
+
});
|
|
6625
|
+
}
|
|
6626
|
+
}
|
|
6627
|
+
|
|
6628
|
+
/**
|
|
6629
|
+
* The `VirtualizedMessageListService` removes messages from the message list that are currently not in view
|
|
6630
|
+
*/
|
|
6631
|
+
class VirtualizedMessageListService extends VirtualizedListService {
|
|
6632
|
+
constructor(mode, scrollPosition$, channelService) {
|
|
6633
|
+
const jumpToMessage$ = channelService.jumpToMessage$.pipe(map$1((jumpToMessage) => {
|
|
6634
|
+
var _a;
|
|
6635
|
+
let result = {
|
|
6636
|
+
item: undefined,
|
|
6637
|
+
};
|
|
6638
|
+
let targetMessageId;
|
|
6639
|
+
if (mode === 'main') {
|
|
6640
|
+
targetMessageId = jumpToMessage.parentId
|
|
6641
|
+
? jumpToMessage.parentId
|
|
6642
|
+
: jumpToMessage.id;
|
|
6643
|
+
}
|
|
6644
|
+
else {
|
|
6645
|
+
targetMessageId = jumpToMessage.parentId
|
|
6646
|
+
? jumpToMessage.id
|
|
6647
|
+
: undefined;
|
|
6648
|
+
}
|
|
6649
|
+
if (targetMessageId) {
|
|
6650
|
+
const messages = mode === 'main'
|
|
6651
|
+
? channelService.activeChannelMessages
|
|
6652
|
+
: channelService.activeChannelThreadReplies;
|
|
6653
|
+
const id = targetMessageId === 'latest'
|
|
6654
|
+
? (_a = messages[messages.length - 1]) === null || _a === void 0 ? void 0 : _a.id
|
|
6655
|
+
: targetMessageId;
|
|
6656
|
+
if (id) {
|
|
6657
|
+
result = {
|
|
6658
|
+
item: { id },
|
|
6659
|
+
position: jumpToMessage.id === 'latest' ? 'bottom' : 'middle',
|
|
6660
|
+
};
|
|
6661
|
+
}
|
|
6662
|
+
channelService.clearMessageJump();
|
|
6663
|
+
}
|
|
6664
|
+
return result;
|
|
6665
|
+
}));
|
|
6666
|
+
const messages$ = mode === 'main'
|
|
6667
|
+
? channelService.activeChannelMessages$
|
|
6668
|
+
: channelService.activeThreadMessages$;
|
|
6669
|
+
super(messages$, scrollPosition$, jumpToMessage$, channelService.messagePageSize);
|
|
6670
|
+
this.mode = mode;
|
|
6671
|
+
this.channelService = channelService;
|
|
6672
|
+
this.isEqual = (t1, t2) => t1.id === t2.id;
|
|
6673
|
+
this.query = (direction) => {
|
|
6674
|
+
const request = this.mode === 'main'
|
|
6675
|
+
? (direction) => this.channelService.loadMoreMessages(direction)
|
|
6676
|
+
: (direction) => this.channelService.loadMoreThreadReplies(direction);
|
|
6677
|
+
const result = request(direction === 'top' ? 'older' : 'newer');
|
|
6678
|
+
if (result) {
|
|
6679
|
+
return result;
|
|
6680
|
+
}
|
|
6681
|
+
else {
|
|
6682
|
+
this.queryStateSubject.next({ state: 'success' });
|
|
6683
|
+
if ((direction === 'top' && this.bufferOnTop > 0) ||
|
|
6684
|
+
(direction === 'bottom' && this.bufferOnBottom > 0)) {
|
|
6685
|
+
this.loadFromBuffer$.next();
|
|
6686
|
+
}
|
|
6687
|
+
return Promise.resolve();
|
|
6688
|
+
}
|
|
6689
|
+
};
|
|
6690
|
+
}
|
|
6691
|
+
loadMoreFromBuffer(direction) {
|
|
6692
|
+
this.queryStateSubject.next({ state: `loading-${direction}` });
|
|
6693
|
+
setTimeout(() => {
|
|
6694
|
+
this.loadFromBuffer$.next();
|
|
6695
|
+
this.queryStateSubject.next({ state: 'success' });
|
|
6696
|
+
});
|
|
6697
|
+
}
|
|
6698
|
+
}
|
|
6699
|
+
|
|
6368
6700
|
/**
|
|
6369
6701
|
* The `MessageList` component renders a scrollable list of messages.
|
|
6370
6702
|
*/
|
|
@@ -6415,10 +6747,6 @@ class MessageListComponent {
|
|
|
6415
6747
|
* You can turn on and off the loading indicator that signals to users that more messages are being loaded to the message list
|
|
6416
6748
|
*/
|
|
6417
6749
|
this.displayLoadingIndicator = true;
|
|
6418
|
-
/**
|
|
6419
|
-
* @internal
|
|
6420
|
-
*/
|
|
6421
|
-
this.limitNumberOfMessagesInList = true;
|
|
6422
6750
|
this.emptyMainMessageListTemplate = null;
|
|
6423
6751
|
this.emptyThreadMessageListTemplate = null;
|
|
6424
6752
|
this.enabledMessageActions = [];
|
|
@@ -6426,17 +6754,20 @@ class MessageListComponent {
|
|
|
6426
6754
|
this.newMessageCountWhileBeingScrolled = 0;
|
|
6427
6755
|
this.groupStyles = [];
|
|
6428
6756
|
this.isNextMessageOnSeparateDate = [];
|
|
6429
|
-
this.
|
|
6757
|
+
this.loadingState = 'idle';
|
|
6430
6758
|
this.isUnreadNotificationVisible = true;
|
|
6431
6759
|
this.isJumpingToLatestUnreadMessage = false;
|
|
6432
6760
|
this.isJumpToLatestButtonVisible = true;
|
|
6761
|
+
this.isJumpingToMessage = false;
|
|
6433
6762
|
this.scroll$ = new Subject();
|
|
6763
|
+
this.isNewMessageSentByUser = false;
|
|
6434
6764
|
this.subscriptions = [];
|
|
6435
6765
|
this.isLatestMessageInList = true;
|
|
6436
6766
|
this.parsedDates = new Map();
|
|
6437
6767
|
this.isViewInited = false;
|
|
6438
6768
|
this.isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent);
|
|
6439
6769
|
this.forceRepaintSubject = new Subject();
|
|
6770
|
+
this.scrollPosition$ = new BehaviorSubject('bottom');
|
|
6440
6771
|
this.messageNotificationJumpClicked = () => {
|
|
6441
6772
|
this.jumpToFirstUnreadMessage();
|
|
6442
6773
|
this.isUnreadNotificationVisible = false;
|
|
@@ -6455,8 +6786,7 @@ class MessageListComponent {
|
|
|
6455
6786
|
this.forceRepaint();
|
|
6456
6787
|
}));
|
|
6457
6788
|
this.subscriptions.push(this.channelService.activeChannel$.subscribe((channel) => {
|
|
6458
|
-
var _a, _b
|
|
6459
|
-
(_b = (_a = this.chatClientService.chatClient) === null || _a === void 0 ? void 0 : _a.logger) === null || _b === void 0 ? void 0 : _b.call(_a, 'info', `${(channel === null || channel === void 0 ? void 0 : channel.cid) || 'undefined'} selected`, { tags: `message list ${this.mode}` });
|
|
6789
|
+
var _a, _b;
|
|
6460
6790
|
let isNewChannel = false;
|
|
6461
6791
|
if (this.channelId !== (channel === null || channel === void 0 ? void 0 : channel.id)) {
|
|
6462
6792
|
isNewChannel = true;
|
|
@@ -6464,12 +6794,9 @@ class MessageListComponent {
|
|
|
6464
6794
|
clearTimeout(this.checkIfUnreadNotificationIsVisibleTimeout);
|
|
6465
6795
|
}
|
|
6466
6796
|
this.isUnreadNotificationVisible = false;
|
|
6467
|
-
(_e = (_d = (_c = this.chatClientService) === null || _c === void 0 ? void 0 : _c.chatClient) === null || _d === void 0 ? void 0 : _d.logger) === null || _e === void 0 ? void 0 : _e.call(_d, 'info', `new channel is different from prev channel, reseting scroll state`, { tags: `message list ${this.mode}` });
|
|
6468
6797
|
this.parsedDates = new Map();
|
|
6469
|
-
if (this.messageRemoveTimeout) {
|
|
6470
|
-
clearTimeout(this.messageRemoveTimeout);
|
|
6471
|
-
}
|
|
6472
6798
|
this.resetScrollState();
|
|
6799
|
+
this.setMessages$();
|
|
6473
6800
|
this.channelId = channel === null || channel === void 0 ? void 0 : channel.id;
|
|
6474
6801
|
if (this.isViewInited) {
|
|
6475
6802
|
this.cdRef.detectChanges();
|
|
@@ -6516,7 +6843,7 @@ class MessageListComponent {
|
|
|
6516
6843
|
this.cdRef.detectChanges();
|
|
6517
6844
|
}
|
|
6518
6845
|
}
|
|
6519
|
-
const capabilites = (
|
|
6846
|
+
const capabilites = (_a = channel === null || channel === void 0 ? void 0 : channel.data) === null || _a === void 0 ? void 0 : _a.own_capabilities;
|
|
6520
6847
|
const capabilitesString = [...(capabilites || [])].sort().join('');
|
|
6521
6848
|
const enabledActionsString = [...(this.enabledMessageActions || [])]
|
|
6522
6849
|
.sort()
|
|
@@ -6527,20 +6854,15 @@ class MessageListComponent {
|
|
|
6527
6854
|
this.cdRef.detectChanges();
|
|
6528
6855
|
}
|
|
6529
6856
|
}
|
|
6530
|
-
(
|
|
6857
|
+
(_b = this.newMessageSubscription) === null || _b === void 0 ? void 0 : _b.unsubscribe();
|
|
6531
6858
|
if (channel) {
|
|
6532
6859
|
this.newMessageSubscription = channel.on('message.new', (event) => {
|
|
6533
|
-
|
|
6534
|
-
if (!event.message ||
|
|
6535
|
-
channel.state.messages === channel.state.latestMessages ||
|
|
6536
|
-
this.mode === 'thread') {
|
|
6860
|
+
if (!event.message) {
|
|
6537
6861
|
return;
|
|
6538
6862
|
}
|
|
6539
|
-
|
|
6540
|
-
|
|
6541
|
-
|
|
6542
|
-
created_at: new Date(event.message.created_at || ''),
|
|
6543
|
-
});
|
|
6863
|
+
else {
|
|
6864
|
+
this.newMessageReceived(event.message);
|
|
6865
|
+
}
|
|
6544
6866
|
});
|
|
6545
6867
|
}
|
|
6546
6868
|
}));
|
|
@@ -6550,6 +6872,7 @@ class MessageListComponent {
|
|
|
6550
6872
|
message.id !== this.parentMessage.id &&
|
|
6551
6873
|
this.mode === 'thread') {
|
|
6552
6874
|
this.resetScrollState();
|
|
6875
|
+
this.setMessages$();
|
|
6553
6876
|
}
|
|
6554
6877
|
if (this.parentMessage === message) {
|
|
6555
6878
|
return;
|
|
@@ -6604,42 +6927,6 @@ class MessageListComponent {
|
|
|
6604
6927
|
this.cdRef.detectChanges();
|
|
6605
6928
|
}
|
|
6606
6929
|
}));
|
|
6607
|
-
this.subscriptions.push(this.channelService.jumpToMessage$
|
|
6608
|
-
.pipe(filter((config) => !!config.id))
|
|
6609
|
-
.subscribe((config) => {
|
|
6610
|
-
var _a, _b;
|
|
6611
|
-
let messageId = undefined;
|
|
6612
|
-
if (this.messageRemoveTimeout) {
|
|
6613
|
-
clearTimeout(this.messageRemoveTimeout);
|
|
6614
|
-
}
|
|
6615
|
-
if (this.mode === 'main') {
|
|
6616
|
-
messageId = config.parentId || config.id;
|
|
6617
|
-
}
|
|
6618
|
-
else if (config.parentId) {
|
|
6619
|
-
messageId = config.id;
|
|
6620
|
-
}
|
|
6621
|
-
(_b = (_a = this.chatClientService.chatClient) === null || _a === void 0 ? void 0 : _a.logger) === null || _b === void 0 ? void 0 : _b.call(_a, 'info', `Jumping to ${messageId || ''}`, { tags: `message list ${this.mode}` });
|
|
6622
|
-
if (messageId) {
|
|
6623
|
-
if (messageId === 'latest') {
|
|
6624
|
-
this.scrollToLatestMessage();
|
|
6625
|
-
if (this.isViewInited) {
|
|
6626
|
-
this.cdRef.detectChanges();
|
|
6627
|
-
}
|
|
6628
|
-
}
|
|
6629
|
-
else {
|
|
6630
|
-
if (this.isJumpingToLatestUnreadMessage) {
|
|
6631
|
-
this.scrollMessageIntoView(this.firstUnreadMessageId || messageId);
|
|
6632
|
-
this.highlightedMessageId =
|
|
6633
|
-
this.firstUnreadMessageId || messageId;
|
|
6634
|
-
}
|
|
6635
|
-
else {
|
|
6636
|
-
this.scrollMessageIntoView(messageId);
|
|
6637
|
-
this.highlightedMessageId = messageId;
|
|
6638
|
-
}
|
|
6639
|
-
}
|
|
6640
|
-
}
|
|
6641
|
-
this.channelService.clearMessageJump();
|
|
6642
|
-
}));
|
|
6643
6930
|
this.subscriptions.push(this.customTemplatesService.emptyMainMessageListPlaceholder$.subscribe((template) => {
|
|
6644
6931
|
const isChanged = this.emptyMainMessageListTemplate !== template;
|
|
6645
6932
|
this.emptyMainMessageListTemplate = template || null;
|
|
@@ -6659,6 +6946,7 @@ class MessageListComponent {
|
|
|
6659
6946
|
ngOnChanges(changes) {
|
|
6660
6947
|
var _a;
|
|
6661
6948
|
if (changes.mode || changes.direction) {
|
|
6949
|
+
this.resetScrollState();
|
|
6662
6950
|
this.setMessages$();
|
|
6663
6951
|
}
|
|
6664
6952
|
if (changes.direction) {
|
|
@@ -6670,56 +6958,33 @@ class MessageListComponent {
|
|
|
6670
6958
|
ngAfterViewInit() {
|
|
6671
6959
|
this.isViewInited = true;
|
|
6672
6960
|
this.ngZone.runOutsideAngular(() => {
|
|
6673
|
-
|
|
6961
|
+
var _a, _b;
|
|
6962
|
+
(_b = (_a = this.scrollContainer) === null || _a === void 0 ? void 0 : _a.nativeElement) === null || _b === void 0 ? void 0 : _b.addEventListener('scroll', () => this.scrolled());
|
|
6674
6963
|
});
|
|
6675
6964
|
}
|
|
6676
6965
|
ngAfterViewChecked() {
|
|
6677
|
-
var _a, _b
|
|
6678
|
-
if (this.
|
|
6679
|
-
|
|
6680
|
-
this.
|
|
6681
|
-
this.
|
|
6966
|
+
var _a, _b;
|
|
6967
|
+
if (this.isJumpingToMessage) {
|
|
6968
|
+
this.isNewMessageSentByUser = false;
|
|
6969
|
+
this.messageIdToAnchorTo = undefined;
|
|
6970
|
+
this.anchorMessageTopOffset = undefined;
|
|
6971
|
+
return;
|
|
6682
6972
|
}
|
|
6683
|
-
if (this.
|
|
6684
|
-
|
|
6685
|
-
(this.isNewMessageSentByUser || !this.isUserScrolled)) {
|
|
6686
|
-
this.isLatestMessageInList
|
|
6687
|
-
? this.scrollToTop()
|
|
6688
|
-
: this.jumpToLatestMessage();
|
|
6689
|
-
this.hasNewMessages = false;
|
|
6690
|
-
this.containerHeight = this.scrollContainer.nativeElement.scrollHeight;
|
|
6691
|
-
}
|
|
6973
|
+
if (this.messageIdToAnchorTo && this.loadingState === 'idle') {
|
|
6974
|
+
this.preserveScrollbarPosition();
|
|
6692
6975
|
}
|
|
6693
|
-
else
|
|
6694
|
-
|
|
6695
|
-
|
|
6696
|
-
|
|
6697
|
-
|
|
6698
|
-
|
|
6699
|
-
|
|
6700
|
-
|
|
6701
|
-
this.hasNewMessages = false;
|
|
6702
|
-
this.containerHeight = this.scrollContainer.nativeElement.scrollHeight;
|
|
6703
|
-
}
|
|
6704
|
-
else if (this.olderMassagesLoaded) {
|
|
6705
|
-
(_d = (_c = this.chatClientService.chatClient) === null || _c === void 0 ? void 0 : _c.logger) === null || _d === void 0 ? void 0 : _d.call(_c, 'info', `Older messages are loaded, we preserve the scroll position`, { tags: `message list ${this.mode}` });
|
|
6706
|
-
this.preserveScrollbarPosition();
|
|
6707
|
-
this.containerHeight = this.scrollContainer.nativeElement.scrollHeight;
|
|
6708
|
-
this.olderMassagesLoaded = false;
|
|
6709
|
-
}
|
|
6710
|
-
else if (this.getScrollPosition() !== 'bottom' &&
|
|
6711
|
-
!this.isUserScrolled &&
|
|
6712
|
-
!this.highlightedMessageId) {
|
|
6713
|
-
(_f = (_e = this.chatClientService.chatClient) === null || _e === void 0 ? void 0 : _e.logger) === null || _f === void 0 ? void 0 : _f.call(_e, 'info', `Container grew and user didn't scroll therefore we ${this.isLatestMessageInList ? 'scroll' : 'jump'} to latest message`, { tags: `message list ${this.mode}` });
|
|
6714
|
-
this.isLatestMessageInList
|
|
6715
|
-
? this.scrollToBottom()
|
|
6716
|
-
: this.jumpToLatestMessage();
|
|
6717
|
-
this.containerHeight = this.scrollContainer.nativeElement.scrollHeight;
|
|
6718
|
-
}
|
|
6976
|
+
else if ((!this.isUserScrolled &&
|
|
6977
|
+
((_a = this.scrollContainer.nativeElement) === null || _a === void 0 ? void 0 : _a.scrollHeight) >
|
|
6978
|
+
((_b = this.scrollContainer) === null || _b === void 0 ? void 0 : _b.nativeElement.clientHeight) &&
|
|
6979
|
+
this.getScrollPosition() !==
|
|
6980
|
+
(this.direction === 'bottom-to-top' ? 'bottom' : 'top')) ||
|
|
6981
|
+
(this.isUserScrolled && this.isNewMessageSentByUser)) {
|
|
6982
|
+
this.isNewMessageSentByUser = false;
|
|
6983
|
+
this.jumpToLatestMessage();
|
|
6719
6984
|
}
|
|
6720
6985
|
}
|
|
6721
6986
|
ngOnDestroy() {
|
|
6722
|
-
var _a
|
|
6987
|
+
var _a;
|
|
6723
6988
|
this.subscriptions.forEach((s) => s.unsubscribe());
|
|
6724
6989
|
(_a = this.newMessageSubscription) === null || _a === void 0 ? void 0 : _a.unsubscribe();
|
|
6725
6990
|
if (this.scrollEndTimeout) {
|
|
@@ -6731,20 +6996,24 @@ class MessageListComponent {
|
|
|
6731
6996
|
if (this.jumpToLatestButtonVisibilityTimeout) {
|
|
6732
6997
|
clearTimeout(this.jumpToLatestButtonVisibilityTimeout);
|
|
6733
6998
|
}
|
|
6734
|
-
|
|
6735
|
-
clearTimeout(this.messageRemoveTimeout);
|
|
6736
|
-
}
|
|
6737
|
-
(_b = this.removeOldMessagesSubscription) === null || _b === void 0 ? void 0 : _b.unsubscribe();
|
|
6999
|
+
this.disposeVirtualizedList();
|
|
6738
7000
|
}
|
|
6739
|
-
trackByMessageId(
|
|
7001
|
+
trackByMessageId(_, item) {
|
|
6740
7002
|
return item.id;
|
|
6741
7003
|
}
|
|
6742
|
-
trackByUserId(
|
|
7004
|
+
trackByUserId(_, user) {
|
|
6743
7005
|
return user.id;
|
|
6744
7006
|
}
|
|
6745
7007
|
jumpToLatestMessage() {
|
|
6746
7008
|
var _a;
|
|
6747
|
-
|
|
7009
|
+
if (this.isLatestMessageInList) {
|
|
7010
|
+
this.direction === 'bottom-to-top'
|
|
7011
|
+
? this.scrollToBottom()
|
|
7012
|
+
: this.scrollToTop();
|
|
7013
|
+
}
|
|
7014
|
+
else {
|
|
7015
|
+
void this.channelService.jumpToMessage('latest', this.mode === 'thread' ? (_a = this.parentMessage) === null || _a === void 0 ? void 0 : _a.id : undefined);
|
|
7016
|
+
}
|
|
6748
7017
|
}
|
|
6749
7018
|
scrollToBottom() {
|
|
6750
7019
|
this.scrollContainer.nativeElement.scrollTop =
|
|
@@ -6757,7 +7026,7 @@ class MessageListComponent {
|
|
|
6757
7026
|
this.scrollContainer.nativeElement.scrollTop = 0;
|
|
6758
7027
|
}
|
|
6759
7028
|
scrolled() {
|
|
6760
|
-
var _a
|
|
7029
|
+
var _a;
|
|
6761
7030
|
if (this.scrollContainer.nativeElement.scrollHeight ===
|
|
6762
7031
|
this.scrollContainer.nativeElement.clientHeight) {
|
|
6763
7032
|
if (this.isJumpToLatestButtonVisible) {
|
|
@@ -6768,8 +7037,7 @@ class MessageListComponent {
|
|
|
6768
7037
|
return;
|
|
6769
7038
|
}
|
|
6770
7039
|
this.scroll$.next();
|
|
6771
|
-
|
|
6772
|
-
(_b = (_a = this.chatClientService.chatClient) === null || _a === void 0 ? void 0 : _a.logger) === null || _b === void 0 ? void 0 : _b.call(_a, 'info', `Scrolled - scroll position: ${scrollPosition}, container height: ${this.scrollContainer.nativeElement.scrollHeight}`, { tags: `message list ${this.mode}` });
|
|
7040
|
+
let scrollPosition = this.getScrollPosition();
|
|
6773
7041
|
const isUserScrolled = (this.direction === 'bottom-to-top'
|
|
6774
7042
|
? scrollPosition !== 'bottom'
|
|
6775
7043
|
: scrollPosition !== 'top') || !this.isLatestMessageInList;
|
|
@@ -6798,31 +7066,31 @@ class MessageListComponent {
|
|
|
6798
7066
|
}
|
|
6799
7067
|
}, 100);
|
|
6800
7068
|
}
|
|
6801
|
-
|
|
7069
|
+
const prevScrollPosition = this.scrollPosition$.getValue();
|
|
7070
|
+
if (this.direction === 'top-to-bottom') {
|
|
7071
|
+
if (scrollPosition === 'top') {
|
|
7072
|
+
scrollPosition = 'bottom';
|
|
7073
|
+
}
|
|
7074
|
+
else if (scrollPosition === 'bottom') {
|
|
7075
|
+
scrollPosition = 'top';
|
|
7076
|
+
}
|
|
7077
|
+
}
|
|
7078
|
+
if (prevScrollPosition !== scrollPosition && !this.isJumpingToMessage) {
|
|
7079
|
+
if (scrollPosition === 'top' || scrollPosition === 'bottom') {
|
|
7080
|
+
(_a = this.virtualizedList) === null || _a === void 0 ? void 0 : _a.virtualizedItems$.pipe(take(1)).subscribe((items) => {
|
|
7081
|
+
var _a, _b, _c, _d;
|
|
7082
|
+
this.messageIdToAnchorTo =
|
|
7083
|
+
scrollPosition === 'top'
|
|
7084
|
+
? (_a = items[0]) === null || _a === void 0 ? void 0 : _a.id
|
|
7085
|
+
: (_b = items[items.length - 1]) === null || _b === void 0 ? void 0 : _b.id;
|
|
7086
|
+
this.anchorMessageTopOffset = (_d = (_c = document
|
|
7087
|
+
.getElementById(this.messageIdToAnchorTo)) === null || _c === void 0 ? void 0 : _c.getBoundingClientRect()) === null || _d === void 0 ? void 0 : _d.top;
|
|
7088
|
+
});
|
|
7089
|
+
}
|
|
6802
7090
|
this.ngZone.run(() => {
|
|
6803
|
-
|
|
6804
|
-
this.containerHeight = this.scrollContainer.nativeElement.scrollHeight;
|
|
6805
|
-
let direction;
|
|
6806
|
-
if (this.direction === 'top-to-bottom') {
|
|
6807
|
-
direction = scrollPosition === 'top' ? 'newer' : 'older';
|
|
6808
|
-
}
|
|
6809
|
-
else {
|
|
6810
|
-
direction = scrollPosition === 'top' ? 'older' : 'newer';
|
|
6811
|
-
}
|
|
6812
|
-
const result = this.mode === 'main'
|
|
6813
|
-
? this.channelService.loadMoreMessages(direction)
|
|
6814
|
-
: this.channelService.loadMoreThreadReplies(direction);
|
|
6815
|
-
if (result) {
|
|
6816
|
-
(_b = (_a = this.chatClientService.chatClient) === null || _a === void 0 ? void 0 : _a.logger) === null || _b === void 0 ? void 0 : _b.call(_a, 'info', `Displaying loading indicator`, { tags: `message list ${this.mode}` });
|
|
6817
|
-
this.isLoading = true;
|
|
6818
|
-
(_c = result.catch) === null || _c === void 0 ? void 0 : _c.call(result, () => {
|
|
6819
|
-
this.isLoading = false;
|
|
6820
|
-
});
|
|
6821
|
-
}
|
|
6822
|
-
this.cdRef.detectChanges();
|
|
7091
|
+
this.scrollPosition$.next(scrollPosition);
|
|
6823
7092
|
});
|
|
6824
7093
|
}
|
|
6825
|
-
this.prevScrollTop = this.scrollContainer.nativeElement.scrollTop;
|
|
6826
7094
|
}
|
|
6827
7095
|
jumpToFirstUnreadMessage() {
|
|
6828
7096
|
if (!this.lastReadMessageId) {
|
|
@@ -6865,9 +7133,19 @@ class MessageListComponent {
|
|
|
6865
7133
|
: this.emptyThreadMessageListTemplate;
|
|
6866
7134
|
}
|
|
6867
7135
|
preserveScrollbarPosition() {
|
|
6868
|
-
|
|
6869
|
-
|
|
6870
|
-
|
|
7136
|
+
var _a;
|
|
7137
|
+
if (!this.messageIdToAnchorTo) {
|
|
7138
|
+
return;
|
|
7139
|
+
}
|
|
7140
|
+
const messageToAlignTo = document.getElementById(this.messageIdToAnchorTo);
|
|
7141
|
+
this.messageIdToAnchorTo = undefined;
|
|
7142
|
+
this.scrollContainer.nativeElement.scrollTop +=
|
|
7143
|
+
(((_a = messageToAlignTo === null || messageToAlignTo === void 0 ? void 0 : messageToAlignTo.getBoundingClientRect()) === null || _a === void 0 ? void 0 : _a.top) || 0) -
|
|
7144
|
+
(this.anchorMessageTopOffset || 0);
|
|
7145
|
+
this.anchorMessageTopOffset = undefined;
|
|
7146
|
+
if (this.isSafari) {
|
|
7147
|
+
this.forceRepaintSubject.next();
|
|
7148
|
+
}
|
|
6871
7149
|
}
|
|
6872
7150
|
forceRepaint() {
|
|
6873
7151
|
// Solves the issue of empty screen on Safari when scrolling
|
|
@@ -6876,13 +7154,10 @@ class MessageListComponent {
|
|
|
6876
7154
|
this.scrollContainer.nativeElement.style.display = '';
|
|
6877
7155
|
}
|
|
6878
7156
|
getScrollPosition() {
|
|
6879
|
-
var _a
|
|
7157
|
+
var _a;
|
|
6880
7158
|
let position = 'middle';
|
|
6881
7159
|
if (Math.floor(this.scrollContainer.nativeElement.scrollTop) <=
|
|
6882
|
-
(((_a = this.parentMessageElement) === null || _a === void 0 ? void 0 : _a.nativeElement.clientHeight) || 0)
|
|
6883
|
-
(this.prevScrollTop === undefined ||
|
|
6884
|
-
this.prevScrollTop >
|
|
6885
|
-
(((_b = this.parentMessageElement) === null || _b === void 0 ? void 0 : _b.nativeElement.clientHeight) || 0))) {
|
|
7160
|
+
(((_a = this.parentMessageElement) === null || _a === void 0 ? void 0 : _a.nativeElement.clientHeight) || 0)) {
|
|
6886
7161
|
position = 'top';
|
|
6887
7162
|
}
|
|
6888
7163
|
else if (Math.ceil(this.scrollContainer.nativeElement.scrollTop) +
|
|
@@ -6893,24 +7168,24 @@ class MessageListComponent {
|
|
|
6893
7168
|
}
|
|
6894
7169
|
return position;
|
|
6895
7170
|
}
|
|
6896
|
-
shouldLoadMoreMessages(scrollPosition) {
|
|
6897
|
-
return (scrollPosition !== 'middle' &&
|
|
6898
|
-
!this.highlightedMessageId &&
|
|
6899
|
-
!this.isLoading);
|
|
6900
|
-
}
|
|
6901
7171
|
setMessages$() {
|
|
6902
7172
|
var _a;
|
|
6903
|
-
this.
|
|
6904
|
-
|
|
6905
|
-
|
|
6906
|
-
|
|
6907
|
-
if (
|
|
6908
|
-
|
|
7173
|
+
this.disposeVirtualizedList();
|
|
7174
|
+
this.virtualizedList = new VirtualizedMessageListService(this.mode, this.scrollPosition$, this.channelService);
|
|
7175
|
+
this.queryStateSubscription = this.virtualizedList.queryState$.subscribe((queryState) => {
|
|
7176
|
+
let mappedState = 'idle';
|
|
7177
|
+
if (queryState.state.includes('loading')) {
|
|
7178
|
+
mappedState = queryState.state || 'loading-bottom';
|
|
7179
|
+
}
|
|
7180
|
+
if (mappedState !== this.loadingState) {
|
|
7181
|
+
this.loadingState = mappedState;
|
|
7182
|
+
if (this.isViewInited) {
|
|
7183
|
+
this.cdRef.detectChanges();
|
|
7184
|
+
}
|
|
6909
7185
|
}
|
|
7186
|
+
});
|
|
7187
|
+
this.messages$ = this.virtualizedList.virtualizedItems$.pipe(tap((messages) => {
|
|
6910
7188
|
if (messages.length === 0) {
|
|
6911
|
-
(_b = (_a = this.chatClientService.chatClient) === null || _a === void 0 ? void 0 : _a.logger) === null || _b === void 0 ? void 0 : _b.call(_a, 'info', `Empty messages array, reseting scroll state`, {
|
|
6912
|
-
tags: `message list ${this.mode}`,
|
|
6913
|
-
});
|
|
6914
7189
|
this.resetScrollState();
|
|
6915
7190
|
return;
|
|
6916
7191
|
}
|
|
@@ -6918,21 +7193,6 @@ class MessageListComponent {
|
|
|
6918
7193
|
// cdRef.detectChanges() isn't enough here, test will fail
|
|
6919
7194
|
setTimeout(() => (this.isEmpty = false), 0);
|
|
6920
7195
|
}
|
|
6921
|
-
(_d = (_c = this.chatClientService.chatClient) === null || _c === void 0 ? void 0 : _c.logger) === null || _d === void 0 ? void 0 : _d.call(_c, 'info', `Received one or more messages`, {
|
|
6922
|
-
tags: `message list ${this.mode}`,
|
|
6923
|
-
});
|
|
6924
|
-
const currentLatestMessageInState = messages[messages.length - 1];
|
|
6925
|
-
this.newMessageReceived(currentLatestMessageInState);
|
|
6926
|
-
const currentOldestMessage = messages[0];
|
|
6927
|
-
if (!this.oldestMessage ||
|
|
6928
|
-
!messages.find((m) => m.id === this.oldestMessage.id)) {
|
|
6929
|
-
this.oldestMessage = currentOldestMessage;
|
|
6930
|
-
}
|
|
6931
|
-
else if (this.oldestMessage.created_at.getTime() >
|
|
6932
|
-
currentOldestMessage.created_at.getTime()) {
|
|
6933
|
-
this.oldestMessage = currentOldestMessage;
|
|
6934
|
-
this.olderMassagesLoaded = true;
|
|
6935
|
-
}
|
|
6936
7196
|
}), tap((messages) => {
|
|
6937
7197
|
var _a;
|
|
6938
7198
|
if (this.isJumpingToLatestUnreadMessage &&
|
|
@@ -6952,82 +7212,101 @@ class MessageListComponent {
|
|
|
6952
7212
|
m.status !== 'sending';
|
|
6953
7213
|
})) === null || _a === void 0 ? void 0 : _a.id);
|
|
6954
7214
|
}), tap((messages) => {
|
|
7215
|
+
var _a, _b;
|
|
7216
|
+
const latestMessageInList = messages[messages.length - 1];
|
|
7217
|
+
const channel = this.channelService.activeChannel;
|
|
7218
|
+
const messagesFromState = (this.mode === 'main'
|
|
7219
|
+
? channel === null || channel === void 0 ? void 0 : channel.state.latestMessages
|
|
7220
|
+
: channel === null || channel === void 0 ? void 0 : channel.state.threads[((_a = this.parentMessage) === null || _a === void 0 ? void 0 : _a.id) || '']) || [];
|
|
6955
7221
|
this.isLatestMessageInList =
|
|
6956
|
-
!
|
|
6957
|
-
|
|
6958
|
-
|
|
6959
|
-
|
|
7222
|
+
!latestMessageInList ||
|
|
7223
|
+
latestMessageInList.cid !== (channel === null || channel === void 0 ? void 0 : channel.cid) ||
|
|
7224
|
+
(latestMessageInList === null || latestMessageInList === void 0 ? void 0 : latestMessageInList.id) ===
|
|
7225
|
+
((_b = messagesFromState[messagesFromState.length - 1]) === null || _b === void 0 ? void 0 : _b.id);
|
|
6960
7226
|
if (!this.isLatestMessageInList) {
|
|
6961
7227
|
this.isUserScrolled = true;
|
|
6962
7228
|
}
|
|
6963
|
-
}), map((messages) =>
|
|
7229
|
+
}), map((messages) => {
|
|
7230
|
+
return this.direction === 'bottom-to-top'
|
|
7231
|
+
? messages
|
|
7232
|
+
: [...messages].reverse();
|
|
7233
|
+
}), tap((messages) => {
|
|
6964
7234
|
this.groupStyles = messages.map((m, i) => getGroupStyles(m, messages[i - 1], messages[i + 1], {
|
|
6965
7235
|
lastReadMessageId: this.lastReadMessageId,
|
|
6966
7236
|
}));
|
|
6967
7237
|
this.isNextMessageOnSeparateDate = messages.map((m, i) => this.checkIfOnSeparateDates(m, messages[i + 1]));
|
|
6968
7238
|
}), shareReplay(1));
|
|
6969
|
-
(_a = this.
|
|
6970
|
-
|
|
6971
|
-
|
|
6972
|
-
|
|
6973
|
-
|
|
6974
|
-
|
|
6975
|
-
|
|
6976
|
-
|
|
6977
|
-
|
|
6978
|
-
|
|
6979
|
-
|
|
6980
|
-
|
|
6981
|
-
|
|
6982
|
-
|
|
6983
|
-
|
|
6984
|
-
|
|
6985
|
-
this.
|
|
6986
|
-
|
|
6987
|
-
|
|
6988
|
-
|
|
6989
|
-
|
|
6990
|
-
this.mode === 'main' &&
|
|
6991
|
-
messages.length >
|
|
6992
|
-
ChannelService.MAX_MESSAGE_COUNT_IN_MESSAGE_LIST * 0.5 &&
|
|
6993
|
-
!this.isUserScrolled &&
|
|
6994
|
-
!this.highlightedMessageId &&
|
|
6995
|
-
this.isLatestMessageInList) {
|
|
6996
|
-
this.channelService.removeOldMessageFromMessageList();
|
|
6997
|
-
}
|
|
6998
|
-
}, 1500);
|
|
7239
|
+
if ((_a = this.virtualizedList) === null || _a === void 0 ? void 0 : _a.jumpToItem$) {
|
|
7240
|
+
this.jumpToItemSubscription = this.virtualizedList.jumpToItem$
|
|
7241
|
+
.pipe(filter((jumpToMessage) => { var _a; return !!((_a = jumpToMessage.item) === null || _a === void 0 ? void 0 : _a.id); }))
|
|
7242
|
+
.subscribe((jumpToMessage) => {
|
|
7243
|
+
var _a;
|
|
7244
|
+
let messageId = (_a = jumpToMessage.item) === null || _a === void 0 ? void 0 : _a.id;
|
|
7245
|
+
if (messageId) {
|
|
7246
|
+
if (this.isJumpingToLatestUnreadMessage) {
|
|
7247
|
+
messageId = this.firstUnreadMessageId || messageId;
|
|
7248
|
+
}
|
|
7249
|
+
if (jumpToMessage.position !== 'bottom') {
|
|
7250
|
+
this.highlightedMessageId = messageId;
|
|
7251
|
+
}
|
|
7252
|
+
else if (this.direction === 'top-to-bottom') {
|
|
7253
|
+
jumpToMessage.position = 'top';
|
|
7254
|
+
}
|
|
7255
|
+
this.isJumpingToMessage = true;
|
|
7256
|
+
this.scrollMessageIntoView({
|
|
7257
|
+
messageId: this.firstUnreadMessageId || messageId,
|
|
7258
|
+
position: jumpToMessage.position || 'middle',
|
|
7259
|
+
});
|
|
6999
7260
|
}
|
|
7000
|
-
}
|
|
7001
|
-
}
|
|
7261
|
+
});
|
|
7262
|
+
}
|
|
7002
7263
|
}
|
|
7003
7264
|
resetScrollState() {
|
|
7004
7265
|
this.isEmpty = true;
|
|
7005
|
-
this.latestMessage = undefined;
|
|
7006
|
-
this.hasNewMessages = true;
|
|
7007
7266
|
this.isUserScrolled = false;
|
|
7008
|
-
this.
|
|
7009
|
-
this.
|
|
7010
|
-
this.oldestMessage = undefined;
|
|
7267
|
+
this.messageIdToAnchorTo = undefined;
|
|
7268
|
+
this.anchorMessageTopOffset = undefined;
|
|
7011
7269
|
this.newMessageCountWhileBeingScrolled = 0;
|
|
7012
|
-
this.
|
|
7013
|
-
this.isNewMessageSentByUser = undefined;
|
|
7270
|
+
this.isNewMessageSentByUser = false;
|
|
7014
7271
|
this.isLatestMessageInList = true;
|
|
7272
|
+
this.isJumpingToMessage = false;
|
|
7273
|
+
this.scrollPosition$.next('bottom');
|
|
7274
|
+
this.loadingState = 'idle';
|
|
7275
|
+
}
|
|
7276
|
+
disposeVirtualizedList() {
|
|
7277
|
+
var _a, _b, _c;
|
|
7278
|
+
(_a = this.virtualizedList) === null || _a === void 0 ? void 0 : _a.dispose();
|
|
7279
|
+
(_b = this.jumpToItemSubscription) === null || _b === void 0 ? void 0 : _b.unsubscribe();
|
|
7280
|
+
(_c = this.queryStateSubscription) === null || _c === void 0 ? void 0 : _c.unsubscribe();
|
|
7015
7281
|
}
|
|
7016
7282
|
get usersTyping$() {
|
|
7017
7283
|
return this.mode === 'thread'
|
|
7018
7284
|
? this.usersTypingInThread$
|
|
7019
7285
|
: this.usersTypingInChannel$;
|
|
7020
7286
|
}
|
|
7021
|
-
scrollMessageIntoView(
|
|
7022
|
-
const element = document.getElementById(messageId);
|
|
7287
|
+
scrollMessageIntoView(options, withRetry = true) {
|
|
7288
|
+
const element = document.getElementById(options.messageId);
|
|
7023
7289
|
if (!element && withRetry) {
|
|
7024
7290
|
// If the message was newly inserted into activeChannelMessages$, the message will be rendered after the current change detection cycle -> wait for this cycle to complete
|
|
7025
|
-
setTimeout(() => this.scrollMessageIntoView(
|
|
7291
|
+
setTimeout(() => this.scrollMessageIntoView(options, false));
|
|
7026
7292
|
}
|
|
7027
7293
|
else if (element) {
|
|
7294
|
+
const blockMapping = {
|
|
7295
|
+
top: 'start',
|
|
7296
|
+
bottom: 'end',
|
|
7297
|
+
middle: 'center',
|
|
7298
|
+
};
|
|
7028
7299
|
element.scrollIntoView({
|
|
7029
|
-
block:
|
|
7300
|
+
block: blockMapping[options.position],
|
|
7030
7301
|
});
|
|
7302
|
+
if (options.position !== 'middle') {
|
|
7303
|
+
options.position === 'bottom'
|
|
7304
|
+
? this.scrollToBottom()
|
|
7305
|
+
: this.scrollToTop();
|
|
7306
|
+
}
|
|
7307
|
+
setTimeout(() => {
|
|
7308
|
+
this.isJumpingToMessage = false;
|
|
7309
|
+
}, 0);
|
|
7031
7310
|
setTimeout(() => {
|
|
7032
7311
|
this.highlightedMessageId = undefined;
|
|
7033
7312
|
this.firstUnreadMessageId = undefined;
|
|
@@ -7036,40 +7315,27 @@ class MessageListComponent {
|
|
|
7036
7315
|
}, 1000);
|
|
7037
7316
|
}
|
|
7038
7317
|
}
|
|
7039
|
-
|
|
7040
|
-
|
|
7041
|
-
|
|
7042
|
-
|
|
7043
|
-
|
|
7318
|
+
newMessageReceived(message) {
|
|
7319
|
+
var _a, _b, _c, _d;
|
|
7320
|
+
if ((this.mode === 'main' && message.parent_id) ||
|
|
7321
|
+
(this.mode === 'thread' && message.parent_id !== ((_a = this.parentMessage) === null || _a === void 0 ? void 0 : _a.id))) {
|
|
7322
|
+
return;
|
|
7044
7323
|
}
|
|
7045
|
-
|
|
7046
|
-
|
|
7047
|
-
|
|
7324
|
+
const isNewMessageSentByCurrentUser = ((_b = message.user) === null || _b === void 0 ? void 0 : _b.id) === ((_d = (_c = this.chatClientService.chatClient) === null || _c === void 0 ? void 0 : _c.user) === null || _d === void 0 ? void 0 : _d.id);
|
|
7325
|
+
let shouldDetectChanges = false;
|
|
7326
|
+
if (!this.isNewMessageSentByUser && isNewMessageSentByCurrentUser) {
|
|
7327
|
+
this.isNewMessageSentByUser = true;
|
|
7328
|
+
shouldDetectChanges = true;
|
|
7048
7329
|
}
|
|
7049
|
-
|
|
7050
|
-
|
|
7051
|
-
|
|
7052
|
-
|
|
7053
|
-
if (!this.
|
|
7054
|
-
|
|
7055
|
-
|
|
7056
|
-
|
|
7057
|
-
|
|
7058
|
-
((_d = latestMessages[latestMessages.length - 1]) === null || _d === void 0 ? void 0 : _d.id) !== this.latestMessage.id)) {
|
|
7059
|
-
(_f = (_e = this.chatClientService.chatClient) === null || _e === void 0 ? void 0 : _e.logger) === null || _f === void 0 ? void 0 : _f.call(_e, 'info', `Received new message`, { tags: `message list ${this.mode}` });
|
|
7060
|
-
const isNewChannel = !this.latestMessage;
|
|
7061
|
-
this.latestMessage = message;
|
|
7062
|
-
this.hasNewMessages = true;
|
|
7063
|
-
this.isNewMessageSentByUser =
|
|
7064
|
-
((_g = message.user) === null || _g === void 0 ? void 0 : _g.id) === ((_j = (_h = this.chatClientService.chatClient) === null || _h === void 0 ? void 0 : _h.user) === null || _j === void 0 ? void 0 : _j.id);
|
|
7065
|
-
if (this.isUserScrolled) {
|
|
7066
|
-
this.newMessageCountWhileBeingScrolled++;
|
|
7067
|
-
}
|
|
7068
|
-
if (!this.isNewMessageSentByUser &&
|
|
7069
|
-
this.unreadCount !== undefined &&
|
|
7070
|
-
!isNewChannel) {
|
|
7071
|
-
this.unreadCount++;
|
|
7072
|
-
}
|
|
7330
|
+
if (this.isUserScrolled) {
|
|
7331
|
+
this.newMessageCountWhileBeingScrolled++;
|
|
7332
|
+
shouldDetectChanges = true;
|
|
7333
|
+
}
|
|
7334
|
+
if (!this.isNewMessageSentByUser && this.unreadCount !== undefined) {
|
|
7335
|
+
this.unreadCount++;
|
|
7336
|
+
shouldDetectChanges = true;
|
|
7337
|
+
}
|
|
7338
|
+
if (shouldDetectChanges && this.isViewInited) {
|
|
7073
7339
|
this.cdRef.detectChanges();
|
|
7074
7340
|
}
|
|
7075
7341
|
}
|
|
@@ -7081,10 +7347,10 @@ class MessageListComponent {
|
|
|
7081
7347
|
}
|
|
7082
7348
|
}
|
|
7083
7349
|
MessageListComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.4", ngImport: i0, type: MessageListComponent, deps: [{ token: ChannelService }, { token: ChatClientService }, { token: CustomTemplatesService }, { token: DateParserService }, { token: i0.NgZone }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
|
|
7084
|
-
MessageListComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.0.4", type: MessageListComponent, selector: "stream-message-list", inputs: { mode: "mode", direction: "direction", hideJumpToLatestButtonDuringScroll: "hideJumpToLatestButtonDuringScroll", displayDateSeparator: "displayDateSeparator", displayUnreadSeparator: "displayUnreadSeparator", dateSeparatorTextPos: "dateSeparatorTextPos", openMessageListAt: "openMessageListAt", hideUnreadCountForNotificationAndIndicator: "hideUnreadCountForNotificationAndIndicator", displayLoadingIndicator: "displayLoadingIndicator", limitNumberOfMessagesInList: "limitNumberOfMessagesInList" }, 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: "<ng-container\n *ngIf=\"\n lastReadMessageId &&\n isUnreadNotificationVisible &&\n openMessageListAt === 'last-message' &&\n displayUnreadSeparator\n \"\n>\n <ng-container\n *ngTemplateOutlet=\"\n customnewMessagesNotificationTemplate ||\n defaultUnreadMessagesNotification;\n context: {\n unreadCount: unreadCount,\n onDismiss: messageNotificationDismissClicked,\n onJump: messageNotificationJumpClicked\n }\n \"\n ></ng-container>\n</ng-container>\n<ng-template\n #defaultUnreadMessagesNotification\n let-unreadCount=\"unreadCount\"\n let-onDismiss=\"onDismiss\"\n let-onJump=\"onJump\"\n>\n <div\n class=\"str-chat__unread-messages-notification\"\n data-testid=\"unread-messages-notification\"\n >\n <button\n data-testid=\"unread-messages-notification-jump-to-message\"\n (click)=\"onJump()\"\n >\n <ng-container\n *ngIf=\"\n unreadCount > 0 && !hideUnreadCountForNotificationAndIndicator;\n else noUnreadCount\n \"\n >\n {{\n (unreadCount === 1\n ? \"streamChat.\\{\\{count\\}\\} unread message\"\n : \"streamChat.\\{\\{count\\}\\} unread messages\"\n ) | translate: { count: unreadCount }\n }}\n </ng-container>\n <ng-template #noUnreadCount>\n {{ \"streamChat.Unread messages\" | translate }}\n </ng-template>\n </button>\n <button\n data-testid=\"unread-messages-notification-dismiss\"\n (click)=\"onDismiss()\"\n >\n <stream-icon-placeholder icon=\"close\"></stream-icon-placeholder>\n </button>\n </div>\n</ng-template>\n<div #scrollContainer data-testid=\"scroll-container\" class=\"str-chat__list\">\n <ng-container *ngIf=\"mode === 'main' && isEmpty && emptyListTemplate\">\n <ng-container *ngTemplateOutlet=\"emptyListTemplate\"></ng-container>\n </ng-container>\n <div class=\"str-chat__reverse-infinite-scroll str-chat__message-list-scroll\">\n <ul class=\"str-chat__ul\">\n <li\n *ngIf=\"mode === 'thread' && parentMessage\"\n #parentMessageElement\n data-testid=\"parent-message\"\n class=\"str-chat__parent-message-li\"\n >\n <ng-container\n *ngTemplateOutlet=\"\n messageTemplateContainer;\n context: { message: parentMessage, index: 'parent' }\n \"\n ></ng-container>\n <div data-testid=\"reply-count\" class=\"str-chat__thread-start\">\n {{parentMessage.reply_count === 1 ? ('streamChat.1 reply' | translate) : ('streamChat.{{ replyCount }}\n replies' | translate:replyCountParam)}}\n </div>\n </li>\n <ng-container *ngIf=\"mode === 'thread' && isEmpty && emptyListTemplate\">\n <ng-container *ngTemplateOutlet=\"emptyListTemplate\"></ng-container>\n </ng-container>\n <stream-loading-indicator\n *ngIf=\"\n isLoading && direction === 'bottom-to-top' && displayLoadingIndicator\n \"\n data-testid=\"top-loading-indicator\"\n ></stream-loading-indicator>\n <ng-container *ngIf=\"messages$ | async as messages\">\n <ng-container\n *ngFor=\"\n let message of messages;\n let i = index;\n let isFirst = first;\n let isLast = last;\n trackBy: trackByMessageId\n \"\n >\n <ng-container *ngIf=\"isFirst\">\n <ng-container\n *ngTemplateOutlet=\"\n dateSeparator;\n context: {\n date: message.created_at,\n parsedDate: parseDate(message.created_at)\n }\n \"\n ></ng-container>\n </ng-container>\n <li\n tabindex=\"0\"\n data-testclass=\"message\"\n class=\"str-chat__li str-chat__li--{{ groupStyles[i] }}\"\n id=\"{{ message.id }}\"\n >\n <ng-container\n *ngTemplateOutlet=\"\n messageTemplateContainer;\n context: { message: message, index: i }\n \"\n ></ng-container>\n </li>\n <ng-container\n *ngIf=\"\n (lastReadMessageId === message?.id &&\n direction === 'bottom-to-top') ||\n (direction === 'top-to-bottom' &&\n lastReadMessageId === messages[i + 1]?.id)\n \"\n >\n <li\n *ngIf=\"displayUnreadSeparator\"\n id=\"stream-chat-new-message-indicator\"\n data-testid=\"new-messages-indicator\"\n class=\"str-chat__li str-chat__unread-messages-separator-wrapper\"\n >\n <ng-container\n *ngTemplateOutlet=\"\n customnewMessagesIndicatorTemplate ||\n defaultNewMessagesIndicator;\n context: { unreadCount: unreadCount }\n \"\n ></ng-container>\n </li>\n </ng-container>\n <ng-container *ngIf=\"isNextMessageOnSeparateDate[i]\">\n <ng-container\n *ngTemplateOutlet=\"\n dateSeparator;\n context: {\n date: messages[i + 1].created_at,\n parsedDate: parseDate(messages[i + 1].created_at)\n }\n \"\n ></ng-container>\n </ng-container>\n </ng-container>\n </ng-container>\n <stream-loading-indicator\n *ngIf=\"\n isLoading && direction === 'top-to-bottom' && displayLoadingIndicator\n \"\n data-testid=\"bottom-loading-indicator\"\n ></stream-loading-indicator>\n </ul>\n <ng-template #defaultTypingIndicator let-usersTyping$=\"usersTyping$\">\n <!-- eslint-disable-next-line @angular-eslint/template/no-any -->\n <ng-container *ngIf=\"$any(usersTyping$ | async) as users\">\n <div\n *ngIf=\"users.length > 0\"\n data-testid=\"typing-indicator\"\n class=\"str-chat__typing-indicator str-chat__typing-indicator--typing\"\n >\n <div class=\"str-chat__typing-indicator__dots\">\n <span class=\"str-chat__typing-indicator__dot\"></span>\n <span class=\"str-chat__typing-indicator__dot\"></span>\n <span class=\"str-chat__typing-indicator__dot\"></span>\n </div>\n <div\n data-testid=\"typing-users\"\n class=\"str-chat__typing-indicator__users\"\n >\n {{\n users.length === 1\n ? (\"streamChat.user is typing\"\n | translate: { user: getTypingIndicatorText(users) })\n : (\"streamChat.users are typing\"\n | translate: { users: getTypingIndicatorText(users) })\n }}\n </div>\n </div>\n </ng-container>\n </ng-template>\n <ng-container\n *ngTemplateOutlet=\"\n typingIndicatorTemplate || defaultTypingIndicator;\n context: getTypingIndicatorContext()\n \"\n ></ng-container>\n </div>\n</div>\n<div class=\"str-chat__jump-to-latest-message\">\n <button\n *ngIf=\"isUserScrolled && isJumpToLatestButtonVisible\"\n data-testid=\"scroll-to-latest\"\n class=\"\n str-chat__message-notification-scroll-to-latest\n str-chat__message-notification-scroll-to-latest-right\n str-chat__circle-fab\n \"\n (keyup.enter)=\"jumpToLatestMessage()\"\n (click)=\"jumpToLatestMessage()\"\n >\n <stream-icon\n class=\"str-chat__jump-to-latest-icon str-chat__circle-fab-icon\"\n [icon]=\"direction === 'bottom-to-top' ? 'arrow-down' : 'arrow-up'\"\n ></stream-icon>\n <div\n *ngIf=\"newMessageCountWhileBeingScrolled > 0\"\n class=\"\n str-chat__message-notification\n str-chat__message-notification-scroll-to-latest-unread-count\n str-chat__jump-to-latest-unread-count\n \"\n >\n {{ newMessageCountWhileBeingScrolled }}\n </div>\n </button>\n</div>\n\n<ng-template #messageTemplateContainer let-message=\"message\" let-index=\"index\">\n <ng-template\n #defaultMessageTemplate\n let-messageInput=\"message\"\n let-isLastSentMessage=\"isLastSentMessage\"\n let-enabledMessageActions=\"enabledMessageActions\"\n let-mode=\"mode\"\n let-isHighlighted=\"isHighlighted\"\n let-scroll$=\"scroll$\"\n >\n <stream-message\n [message]=\"messageInput\"\n [isLastSentMessage]=\"isLastSentMessage\"\n [enabledMessageActions]=\"enabledMessageActions\"\n [mode]=\"mode\"\n [isHighlighted]=\"isHighlighted\"\n [scroll$]=\"scroll$\"\n ></stream-message>\n </ng-template>\n <ng-container\n *ngTemplateOutlet=\"\n messageTemplate || defaultMessageTemplate;\n context: {\n message: message,\n isLastSentMessage: !!(\n lastSentMessageId && message?.id === lastSentMessageId\n ),\n enabledMessageActions: enabledMessageActions,\n mode: mode,\n isHighlighted: message?.id === highlightedMessageId,\n scroll$: scroll$\n }\n \"\n ></ng-container>\n</ng-template>\n\n<ng-template #dateSeparator let-date=\"date\" let-parsedDate=\"parsedDate\">\n <ng-container *ngIf=\"displayDateSeparator\">\n <ng-container\n *ngTemplateOutlet=\"\n customDateSeparatorTemplate || defaultDateSeparator;\n context: {\n date: date,\n parsedDate: parsedDate\n }\n \"\n ></ng-container>\n </ng-container>\n\n <ng-template\n #defaultDateSeparator\n let-date=\"date\"\n let-parsedDate=\"parsedDate\"\n >\n <div data-testid=\"date-separator\" class=\"str-chat__date-separator\">\n <hr\n *ngIf=\"\n dateSeparatorTextPos === 'right' || dateSeparatorTextPos === 'center'\n \"\n class=\"str-chat__date-separator-line\"\n />\n <div class=\"str-chat__date-separator-date\">\n {{ parsedDate }}\n </div>\n <hr\n *ngIf=\"\n dateSeparatorTextPos === 'left' || dateSeparatorTextPos === 'center'\n \"\n class=\"str-chat__date-separator-line\"\n />\n </div>\n </ng-template>\n</ng-template>\n\n<ng-template #defaultNewMessagesIndicator let-unreadCount=\"unreadCount\">\n <div class=\"str-chat__unread-messages-separator\">\n <ng-container\n *ngIf=\"\n unreadCount > 0 && !hideUnreadCountForNotificationAndIndicator;\n else noUnreadCount\n \"\n >\n {{\n (unreadCount === 1\n ? \"streamChat.\\{\\{count\\}\\} unread message\"\n : \"streamChat.\\{\\{count\\}\\} unread messages\"\n ) | translate: { count: unreadCount }\n }}\n </ng-container>\n <ng-template #noUnreadCount>\n {{ \"streamChat.Unread messages\" | translate }}\n </ng-template>\n </div>\n</ng-template>\n", dependencies: [{ kind: "directive", type: i4.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i4.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: MessageComponent, selector: "stream-message", inputs: ["message", "enabledMessageActions", "isLastSentMessage", "mode", "isHighlighted", "scroll$"] }, { kind: "component", type: LoadingIndicatorComponent, selector: "stream-loading-indicator" }, { kind: "component", type: IconComponent, selector: "stream-icon", inputs: ["icon"] }, { kind: "component", type: IconPlaceholderComponent, selector: "stream-icon-placeholder", inputs: ["icon"] }, { kind: "pipe", type: i4.AsyncPipe, name: "async" }, { kind: "pipe", type: i10.TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
7350
|
+
MessageListComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.0.4", type: MessageListComponent, selector: "stream-message-list", inputs: { mode: "mode", direction: "direction", hideJumpToLatestButtonDuringScroll: "hideJumpToLatestButtonDuringScroll", displayDateSeparator: "displayDateSeparator", displayUnreadSeparator: "displayUnreadSeparator", dateSeparatorTextPos: "dateSeparatorTextPos", openMessageListAt: "openMessageListAt", hideUnreadCountForNotificationAndIndicator: "hideUnreadCountForNotificationAndIndicator", displayLoadingIndicator: "displayLoadingIndicator" }, 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: "<ng-container\n *ngIf=\"\n lastReadMessageId &&\n isUnreadNotificationVisible &&\n openMessageListAt === 'last-message' &&\n displayUnreadSeparator\n \"\n>\n <ng-container\n *ngTemplateOutlet=\"\n customnewMessagesNotificationTemplate ||\n defaultUnreadMessagesNotification;\n context: {\n unreadCount: unreadCount,\n onDismiss: messageNotificationDismissClicked,\n onJump: messageNotificationJumpClicked\n }\n \"\n ></ng-container>\n</ng-container>\n<ng-template\n #defaultUnreadMessagesNotification\n let-unreadCount=\"unreadCount\"\n let-onDismiss=\"onDismiss\"\n let-onJump=\"onJump\"\n>\n <div\n class=\"str-chat__unread-messages-notification\"\n data-testid=\"unread-messages-notification\"\n >\n <button\n data-testid=\"unread-messages-notification-jump-to-message\"\n (click)=\"onJump()\"\n >\n <ng-container\n *ngIf=\"\n unreadCount > 0 && !hideUnreadCountForNotificationAndIndicator;\n else noUnreadCount\n \"\n >\n {{\n (unreadCount === 1\n ? \"streamChat.\\{\\{count\\}\\} unread message\"\n : \"streamChat.\\{\\{count\\}\\} unread messages\"\n ) | translate: { count: unreadCount }\n }}\n </ng-container>\n <ng-template #noUnreadCount>\n {{ \"streamChat.Unread messages\" | translate }}\n </ng-template>\n </button>\n <button\n data-testid=\"unread-messages-notification-dismiss\"\n (click)=\"onDismiss()\"\n >\n <stream-icon-placeholder icon=\"close\"></stream-icon-placeholder>\n </button>\n </div>\n</ng-template>\n<div\n #scrollContainer\n data-testid=\"scroll-container\"\n class=\"str-chat__list\"\n style=\"overscroll-behavior-y: none\"\n>\n <ng-container *ngIf=\"mode === 'main' && isEmpty && emptyListTemplate\">\n <ng-container *ngTemplateOutlet=\"emptyListTemplate\"></ng-container>\n </ng-container>\n <div class=\"str-chat__reverse-infinite-scroll str-chat__message-list-scroll\">\n <ul class=\"str-chat__ul\">\n <li\n *ngIf=\"mode === 'thread' && parentMessage\"\n #parentMessageElement\n data-testid=\"parent-message\"\n class=\"str-chat__parent-message-li\"\n >\n <ng-container\n *ngTemplateOutlet=\"\n messageTemplateContainer;\n context: { message: parentMessage, index: 'parent' }\n \"\n ></ng-container>\n <div data-testid=\"reply-count\" class=\"str-chat__thread-start\">\n {{parentMessage.reply_count === 1 ? ('streamChat.1 reply' | translate) : ('streamChat.{{ replyCount }}\n replies' | translate:replyCountParam)}}\n </div>\n </li>\n <ng-container *ngIf=\"mode === 'thread' && isEmpty && emptyListTemplate\">\n <ng-container *ngTemplateOutlet=\"emptyListTemplate\"></ng-container>\n </ng-container>\n <stream-loading-indicator-placeholder\n *ngIf=\"\n ((loadingState === 'loading-top' && direction === 'bottom-to-top') ||\n (loadingState === 'loading-bottom' &&\n direction === 'top-to-bottom')) &&\n displayLoadingIndicator;\n else loadingIndicatorPlaceholder\n \"\n data-testid=\"top-loading-indicator\"\n ></stream-loading-indicator-placeholder>\n <ng-container *ngIf=\"messages$ | async as messages\">\n <ng-container\n *ngFor=\"\n let message of messages;\n let i = index;\n let isFirst = first;\n let isLast = last;\n trackBy: trackByMessageId\n \"\n >\n <ng-container *ngIf=\"isFirst\">\n <ng-container\n *ngTemplateOutlet=\"\n dateSeparator;\n context: {\n date: message.created_at,\n parsedDate: parseDate(message.created_at)\n }\n \"\n ></ng-container>\n </ng-container>\n <li\n tabindex=\"0\"\n data-testclass=\"message\"\n class=\"str-chat__li str-chat__li--{{ groupStyles[i] }}\"\n id=\"{{ message.id }}\"\n >\n <ng-container\n *ngTemplateOutlet=\"\n messageTemplateContainer;\n context: { message: message, index: i }\n \"\n ></ng-container>\n </li>\n <ng-container\n *ngIf=\"\n (lastReadMessageId === message?.id &&\n direction === 'bottom-to-top') ||\n (direction === 'top-to-bottom' &&\n lastReadMessageId === messages[i + 1]?.id)\n \"\n >\n <li\n *ngIf=\"displayUnreadSeparator\"\n id=\"stream-chat-new-message-indicator\"\n data-testid=\"new-messages-indicator\"\n class=\"str-chat__li str-chat__unread-messages-separator-wrapper\"\n >\n <ng-container\n *ngTemplateOutlet=\"\n customnewMessagesIndicatorTemplate ||\n defaultNewMessagesIndicator;\n context: { unreadCount: unreadCount }\n \"\n ></ng-container>\n </li>\n </ng-container>\n <ng-container *ngIf=\"isNextMessageOnSeparateDate[i]\">\n <ng-container\n *ngTemplateOutlet=\"\n dateSeparator;\n context: {\n date: messages[i + 1].created_at,\n parsedDate: parseDate(messages[i + 1].created_at)\n }\n \"\n ></ng-container>\n </ng-container>\n </ng-container>\n </ng-container>\n <stream-loading-indicator-placeholder\n *ngIf=\"\n ((loadingState === 'loading-bottom' &&\n direction === 'bottom-to-top') ||\n (loadingState === 'loading-top' &&\n direction === 'top-to-bottom')) &&\n displayLoadingIndicator;\n else loadingIndicatorPlaceholder\n \"\n data-testid=\"bottom-loading-indicator\"\n ></stream-loading-indicator-placeholder>\n <ng-template #loadingIndicatorPlaceholder>\n <div class=\"str-chat__loading-indicator-placeholder\"></div>\n </ng-template>\n </ul>\n <ng-template #defaultTypingIndicator let-usersTyping$=\"usersTyping$\">\n <!-- eslint-disable-next-line @angular-eslint/template/no-any -->\n <ng-container *ngIf=\"$any(usersTyping$ | async) as users\">\n <div\n *ngIf=\"users.length > 0\"\n data-testid=\"typing-indicator\"\n class=\"str-chat__typing-indicator str-chat__typing-indicator--typing\"\n >\n <div class=\"str-chat__typing-indicator__dots\">\n <span class=\"str-chat__typing-indicator__dot\"></span>\n <span class=\"str-chat__typing-indicator__dot\"></span>\n <span class=\"str-chat__typing-indicator__dot\"></span>\n </div>\n <div\n data-testid=\"typing-users\"\n class=\"str-chat__typing-indicator__users\"\n >\n {{\n users.length === 1\n ? (\"streamChat.user is typing\"\n | translate: { user: getTypingIndicatorText(users) })\n : (\"streamChat.users are typing\"\n | translate: { users: getTypingIndicatorText(users) })\n }}\n </div>\n </div>\n </ng-container>\n </ng-template>\n <ng-container\n *ngTemplateOutlet=\"\n typingIndicatorTemplate || defaultTypingIndicator;\n context: getTypingIndicatorContext()\n \"\n ></ng-container>\n </div>\n</div>\n<div class=\"str-chat__jump-to-latest-message\">\n <button\n *ngIf=\"isUserScrolled && isJumpToLatestButtonVisible\"\n data-testid=\"scroll-to-latest\"\n class=\"\n str-chat__message-notification-scroll-to-latest\n str-chat__message-notification-scroll-to-latest-right\n str-chat__circle-fab\n \"\n (keyup.enter)=\"jumpToLatestMessage()\"\n (click)=\"jumpToLatestMessage()\"\n >\n <stream-icon\n class=\"str-chat__jump-to-latest-icon str-chat__circle-fab-icon\"\n [icon]=\"direction === 'bottom-to-top' ? 'arrow-down' : 'arrow-up'\"\n ></stream-icon>\n <div\n *ngIf=\"newMessageCountWhileBeingScrolled > 0\"\n class=\"\n str-chat__message-notification\n str-chat__message-notification-scroll-to-latest-unread-count\n str-chat__jump-to-latest-unread-count\n \"\n >\n {{ newMessageCountWhileBeingScrolled }}\n </div>\n </button>\n</div>\n\n<ng-template #messageTemplateContainer let-message=\"message\" let-index=\"index\">\n <ng-template\n #defaultMessageTemplate\n let-messageInput=\"message\"\n let-isLastSentMessage=\"isLastSentMessage\"\n let-enabledMessageActions=\"enabledMessageActions\"\n let-mode=\"mode\"\n let-isHighlighted=\"isHighlighted\"\n let-scroll$=\"scroll$\"\n >\n <stream-message\n [message]=\"messageInput\"\n [isLastSentMessage]=\"isLastSentMessage\"\n [enabledMessageActions]=\"enabledMessageActions\"\n [mode]=\"mode\"\n [isHighlighted]=\"isHighlighted\"\n [scroll$]=\"scroll$\"\n ></stream-message>\n </ng-template>\n <ng-container\n *ngTemplateOutlet=\"\n messageTemplate || defaultMessageTemplate;\n context: {\n message: message,\n isLastSentMessage: !!(\n lastSentMessageId && message?.id === lastSentMessageId\n ),\n enabledMessageActions: enabledMessageActions,\n mode: mode,\n isHighlighted: message?.id === highlightedMessageId,\n scroll$: scroll$\n }\n \"\n ></ng-container>\n</ng-template>\n\n<ng-template #dateSeparator let-date=\"date\" let-parsedDate=\"parsedDate\">\n <ng-container *ngIf=\"displayDateSeparator\">\n <ng-container\n *ngTemplateOutlet=\"\n customDateSeparatorTemplate || defaultDateSeparator;\n context: {\n date: date,\n parsedDate: parsedDate\n }\n \"\n ></ng-container>\n </ng-container>\n\n <ng-template\n #defaultDateSeparator\n let-date=\"date\"\n let-parsedDate=\"parsedDate\"\n >\n <div data-testid=\"date-separator\" class=\"str-chat__date-separator\">\n <hr\n *ngIf=\"\n dateSeparatorTextPos === 'right' || dateSeparatorTextPos === 'center'\n \"\n class=\"str-chat__date-separator-line\"\n />\n <div class=\"str-chat__date-separator-date\">\n {{ parsedDate }}\n </div>\n <hr\n *ngIf=\"\n dateSeparatorTextPos === 'left' || dateSeparatorTextPos === 'center'\n \"\n class=\"str-chat__date-separator-line\"\n />\n </div>\n </ng-template>\n</ng-template>\n\n<ng-template #defaultNewMessagesIndicator let-unreadCount=\"unreadCount\">\n <div class=\"str-chat__unread-messages-separator\">\n <ng-container\n *ngIf=\"\n unreadCount > 0 && !hideUnreadCountForNotificationAndIndicator;\n else noUnreadCount\n \"\n >\n {{\n (unreadCount === 1\n ? \"streamChat.\\{\\{count\\}\\} unread message\"\n : \"streamChat.\\{\\{count\\}\\} unread messages\"\n ) | translate: { count: unreadCount }\n }}\n </ng-container>\n <ng-template #noUnreadCount>\n {{ \"streamChat.Unread messages\" | translate }}\n </ng-template>\n </div>\n</ng-template>\n", dependencies: [{ kind: "directive", type: i4.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i4.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: MessageComponent, selector: "stream-message", inputs: ["message", "enabledMessageActions", "isLastSentMessage", "mode", "isHighlighted", "scroll$"] }, { kind: "component", type: IconComponent, selector: "stream-icon", inputs: ["icon"] }, { kind: "component", type: IconPlaceholderComponent, selector: "stream-icon-placeholder", inputs: ["icon"] }, { kind: "component", type: LoadingIndicatorPlaceholderComponent, selector: "stream-loading-indicator-placeholder" }, { kind: "pipe", type: i4.AsyncPipe, name: "async" }, { kind: "pipe", type: i10.TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
7085
7351
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.4", ngImport: i0, type: MessageListComponent, decorators: [{
|
|
7086
7352
|
type: Component,
|
|
7087
|
-
args: [{ selector: 'stream-message-list', changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-container\n *ngIf=\"\n lastReadMessageId &&\n isUnreadNotificationVisible &&\n openMessageListAt === 'last-message' &&\n displayUnreadSeparator\n \"\n>\n <ng-container\n *ngTemplateOutlet=\"\n customnewMessagesNotificationTemplate ||\n defaultUnreadMessagesNotification;\n context: {\n unreadCount: unreadCount,\n onDismiss: messageNotificationDismissClicked,\n onJump: messageNotificationJumpClicked\n }\n \"\n ></ng-container>\n</ng-container>\n<ng-template\n #defaultUnreadMessagesNotification\n let-unreadCount=\"unreadCount\"\n let-onDismiss=\"onDismiss\"\n let-onJump=\"onJump\"\n>\n <div\n class=\"str-chat__unread-messages-notification\"\n data-testid=\"unread-messages-notification\"\n >\n <button\n data-testid=\"unread-messages-notification-jump-to-message\"\n (click)=\"onJump()\"\n >\n <ng-container\n *ngIf=\"\n unreadCount > 0 && !hideUnreadCountForNotificationAndIndicator;\n else noUnreadCount\n \"\n >\n {{\n (unreadCount === 1\n ? \"streamChat.\\{\\{count\\}\\} unread message\"\n : \"streamChat.\\{\\{count\\}\\} unread messages\"\n ) | translate: { count: unreadCount }\n }}\n </ng-container>\n <ng-template #noUnreadCount>\n {{ \"streamChat.Unread messages\" | translate }}\n </ng-template>\n </button>\n <button\n data-testid=\"unread-messages-notification-dismiss\"\n (click)=\"onDismiss()\"\n >\n <stream-icon-placeholder icon=\"close\"></stream-icon-placeholder>\n </button>\n </div>\n</ng-template>\n<div #scrollContainer data-testid=\"scroll-container\" class=\"str-chat__list\">\n <ng-container *ngIf=\"mode === 'main' && isEmpty && emptyListTemplate\">\n <ng-container *ngTemplateOutlet=\"emptyListTemplate\"></ng-container>\n </ng-container>\n <div class=\"str-chat__reverse-infinite-scroll str-chat__message-list-scroll\">\n <ul class=\"str-chat__ul\">\n <li\n *ngIf=\"mode === 'thread' && parentMessage\"\n #parentMessageElement\n data-testid=\"parent-message\"\n class=\"str-chat__parent-message-li\"\n >\n <ng-container\n *ngTemplateOutlet=\"\n messageTemplateContainer;\n context: { message: parentMessage, index: 'parent' }\n \"\n ></ng-container>\n <div data-testid=\"reply-count\" class=\"str-chat__thread-start\">\n {{parentMessage.reply_count === 1 ? ('streamChat.1 reply' | translate) : ('streamChat.{{ replyCount }}\n replies' | translate:replyCountParam)}}\n </div>\n </li>\n <ng-container *ngIf=\"mode === 'thread' && isEmpty && emptyListTemplate\">\n <ng-container *ngTemplateOutlet=\"emptyListTemplate\"></ng-container>\n </ng-container>\n <stream-loading-indicator\n *ngIf=\"\n isLoading && direction === 'bottom-to-top' && displayLoadingIndicator\n \"\n data-testid=\"top-loading-indicator\"\n ></stream-loading-indicator>\n <ng-container *ngIf=\"messages$ | async as messages\">\n <ng-container\n *ngFor=\"\n let message of messages;\n let i = index;\n let isFirst = first;\n let isLast = last;\n trackBy: trackByMessageId\n \"\n >\n <ng-container *ngIf=\"isFirst\">\n <ng-container\n *ngTemplateOutlet=\"\n dateSeparator;\n context: {\n date: message.created_at,\n parsedDate: parseDate(message.created_at)\n }\n \"\n ></ng-container>\n </ng-container>\n <li\n tabindex=\"0\"\n data-testclass=\"message\"\n class=\"str-chat__li str-chat__li--{{ groupStyles[i] }}\"\n id=\"{{ message.id }}\"\n >\n <ng-container\n *ngTemplateOutlet=\"\n messageTemplateContainer;\n context: { message: message, index: i }\n \"\n ></ng-container>\n </li>\n <ng-container\n *ngIf=\"\n (lastReadMessageId === message?.id &&\n direction === 'bottom-to-top') ||\n (direction === 'top-to-bottom' &&\n lastReadMessageId === messages[i + 1]?.id)\n \"\n >\n <li\n *ngIf=\"displayUnreadSeparator\"\n id=\"stream-chat-new-message-indicator\"\n data-testid=\"new-messages-indicator\"\n class=\"str-chat__li str-chat__unread-messages-separator-wrapper\"\n >\n <ng-container\n *ngTemplateOutlet=\"\n customnewMessagesIndicatorTemplate ||\n defaultNewMessagesIndicator;\n context: { unreadCount: unreadCount }\n \"\n ></ng-container>\n </li>\n </ng-container>\n <ng-container *ngIf=\"isNextMessageOnSeparateDate[i]\">\n <ng-container\n *ngTemplateOutlet=\"\n dateSeparator;\n context: {\n date: messages[i + 1].created_at,\n parsedDate: parseDate(messages[i + 1].created_at)\n }\n \"\n ></ng-container>\n </ng-container>\n </ng-container>\n </ng-container>\n <stream-loading-indicator\n *ngIf=\"\n isLoading && direction === 'top-to-bottom' && displayLoadingIndicator\n \"\n data-testid=\"bottom-loading-indicator\"\n ></stream-loading-indicator>\n </ul>\n <ng-template #defaultTypingIndicator let-usersTyping$=\"usersTyping$\">\n <!-- eslint-disable-next-line @angular-eslint/template/no-any -->\n <ng-container *ngIf=\"$any(usersTyping$ | async) as users\">\n <div\n *ngIf=\"users.length > 0\"\n data-testid=\"typing-indicator\"\n class=\"str-chat__typing-indicator str-chat__typing-indicator--typing\"\n >\n <div class=\"str-chat__typing-indicator__dots\">\n <span class=\"str-chat__typing-indicator__dot\"></span>\n <span class=\"str-chat__typing-indicator__dot\"></span>\n <span class=\"str-chat__typing-indicator__dot\"></span>\n </div>\n <div\n data-testid=\"typing-users\"\n class=\"str-chat__typing-indicator__users\"\n >\n {{\n users.length === 1\n ? (\"streamChat.user is typing\"\n | translate: { user: getTypingIndicatorText(users) })\n : (\"streamChat.users are typing\"\n | translate: { users: getTypingIndicatorText(users) })\n }}\n </div>\n </div>\n </ng-container>\n </ng-template>\n <ng-container\n *ngTemplateOutlet=\"\n typingIndicatorTemplate || defaultTypingIndicator;\n context: getTypingIndicatorContext()\n \"\n ></ng-container>\n </div>\n</div>\n<div class=\"str-chat__jump-to-latest-message\">\n <button\n *ngIf=\"isUserScrolled && isJumpToLatestButtonVisible\"\n data-testid=\"scroll-to-latest\"\n class=\"\n str-chat__message-notification-scroll-to-latest\n str-chat__message-notification-scroll-to-latest-right\n str-chat__circle-fab\n \"\n (keyup.enter)=\"jumpToLatestMessage()\"\n (click)=\"jumpToLatestMessage()\"\n >\n <stream-icon\n class=\"str-chat__jump-to-latest-icon str-chat__circle-fab-icon\"\n [icon]=\"direction === 'bottom-to-top' ? 'arrow-down' : 'arrow-up'\"\n ></stream-icon>\n <div\n *ngIf=\"newMessageCountWhileBeingScrolled > 0\"\n class=\"\n str-chat__message-notification\n str-chat__message-notification-scroll-to-latest-unread-count\n str-chat__jump-to-latest-unread-count\n \"\n >\n {{ newMessageCountWhileBeingScrolled }}\n </div>\n </button>\n</div>\n\n<ng-template #messageTemplateContainer let-message=\"message\" let-index=\"index\">\n <ng-template\n #defaultMessageTemplate\n let-messageInput=\"message\"\n let-isLastSentMessage=\"isLastSentMessage\"\n let-enabledMessageActions=\"enabledMessageActions\"\n let-mode=\"mode\"\n let-isHighlighted=\"isHighlighted\"\n let-scroll$=\"scroll$\"\n >\n <stream-message\n [message]=\"messageInput\"\n [isLastSentMessage]=\"isLastSentMessage\"\n [enabledMessageActions]=\"enabledMessageActions\"\n [mode]=\"mode\"\n [isHighlighted]=\"isHighlighted\"\n [scroll$]=\"scroll$\"\n ></stream-message>\n </ng-template>\n <ng-container\n *ngTemplateOutlet=\"\n messageTemplate || defaultMessageTemplate;\n context: {\n message: message,\n isLastSentMessage: !!(\n lastSentMessageId && message?.id === lastSentMessageId\n ),\n enabledMessageActions: enabledMessageActions,\n mode: mode,\n isHighlighted: message?.id === highlightedMessageId,\n scroll$: scroll$\n }\n \"\n ></ng-container>\n</ng-template>\n\n<ng-template #dateSeparator let-date=\"date\" let-parsedDate=\"parsedDate\">\n <ng-container *ngIf=\"displayDateSeparator\">\n <ng-container\n *ngTemplateOutlet=\"\n customDateSeparatorTemplate || defaultDateSeparator;\n context: {\n date: date,\n parsedDate: parsedDate\n }\n \"\n ></ng-container>\n </ng-container>\n\n <ng-template\n #defaultDateSeparator\n let-date=\"date\"\n let-parsedDate=\"parsedDate\"\n >\n <div data-testid=\"date-separator\" class=\"str-chat__date-separator\">\n <hr\n *ngIf=\"\n dateSeparatorTextPos === 'right' || dateSeparatorTextPos === 'center'\n \"\n class=\"str-chat__date-separator-line\"\n />\n <div class=\"str-chat__date-separator-date\">\n {{ parsedDate }}\n </div>\n <hr\n *ngIf=\"\n dateSeparatorTextPos === 'left' || dateSeparatorTextPos === 'center'\n \"\n class=\"str-chat__date-separator-line\"\n />\n </div>\n </ng-template>\n</ng-template>\n\n<ng-template #defaultNewMessagesIndicator let-unreadCount=\"unreadCount\">\n <div class=\"str-chat__unread-messages-separator\">\n <ng-container\n *ngIf=\"\n unreadCount > 0 && !hideUnreadCountForNotificationAndIndicator;\n else noUnreadCount\n \"\n >\n {{\n (unreadCount === 1\n ? \"streamChat.\\{\\{count\\}\\} unread message\"\n : \"streamChat.\\{\\{count\\}\\} unread messages\"\n ) | translate: { count: unreadCount }\n }}\n </ng-container>\n <ng-template #noUnreadCount>\n {{ \"streamChat.Unread messages\" | translate }}\n </ng-template>\n </div>\n</ng-template>\n" }]
|
|
7353
|
+
args: [{ selector: 'stream-message-list', changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-container\n *ngIf=\"\n lastReadMessageId &&\n isUnreadNotificationVisible &&\n openMessageListAt === 'last-message' &&\n displayUnreadSeparator\n \"\n>\n <ng-container\n *ngTemplateOutlet=\"\n customnewMessagesNotificationTemplate ||\n defaultUnreadMessagesNotification;\n context: {\n unreadCount: unreadCount,\n onDismiss: messageNotificationDismissClicked,\n onJump: messageNotificationJumpClicked\n }\n \"\n ></ng-container>\n</ng-container>\n<ng-template\n #defaultUnreadMessagesNotification\n let-unreadCount=\"unreadCount\"\n let-onDismiss=\"onDismiss\"\n let-onJump=\"onJump\"\n>\n <div\n class=\"str-chat__unread-messages-notification\"\n data-testid=\"unread-messages-notification\"\n >\n <button\n data-testid=\"unread-messages-notification-jump-to-message\"\n (click)=\"onJump()\"\n >\n <ng-container\n *ngIf=\"\n unreadCount > 0 && !hideUnreadCountForNotificationAndIndicator;\n else noUnreadCount\n \"\n >\n {{\n (unreadCount === 1\n ? \"streamChat.\\{\\{count\\}\\} unread message\"\n : \"streamChat.\\{\\{count\\}\\} unread messages\"\n ) | translate: { count: unreadCount }\n }}\n </ng-container>\n <ng-template #noUnreadCount>\n {{ \"streamChat.Unread messages\" | translate }}\n </ng-template>\n </button>\n <button\n data-testid=\"unread-messages-notification-dismiss\"\n (click)=\"onDismiss()\"\n >\n <stream-icon-placeholder icon=\"close\"></stream-icon-placeholder>\n </button>\n </div>\n</ng-template>\n<div\n #scrollContainer\n data-testid=\"scroll-container\"\n class=\"str-chat__list\"\n style=\"overscroll-behavior-y: none\"\n>\n <ng-container *ngIf=\"mode === 'main' && isEmpty && emptyListTemplate\">\n <ng-container *ngTemplateOutlet=\"emptyListTemplate\"></ng-container>\n </ng-container>\n <div class=\"str-chat__reverse-infinite-scroll str-chat__message-list-scroll\">\n <ul class=\"str-chat__ul\">\n <li\n *ngIf=\"mode === 'thread' && parentMessage\"\n #parentMessageElement\n data-testid=\"parent-message\"\n class=\"str-chat__parent-message-li\"\n >\n <ng-container\n *ngTemplateOutlet=\"\n messageTemplateContainer;\n context: { message: parentMessage, index: 'parent' }\n \"\n ></ng-container>\n <div data-testid=\"reply-count\" class=\"str-chat__thread-start\">\n {{parentMessage.reply_count === 1 ? ('streamChat.1 reply' | translate) : ('streamChat.{{ replyCount }}\n replies' | translate:replyCountParam)}}\n </div>\n </li>\n <ng-container *ngIf=\"mode === 'thread' && isEmpty && emptyListTemplate\">\n <ng-container *ngTemplateOutlet=\"emptyListTemplate\"></ng-container>\n </ng-container>\n <stream-loading-indicator-placeholder\n *ngIf=\"\n ((loadingState === 'loading-top' && direction === 'bottom-to-top') ||\n (loadingState === 'loading-bottom' &&\n direction === 'top-to-bottom')) &&\n displayLoadingIndicator;\n else loadingIndicatorPlaceholder\n \"\n data-testid=\"top-loading-indicator\"\n ></stream-loading-indicator-placeholder>\n <ng-container *ngIf=\"messages$ | async as messages\">\n <ng-container\n *ngFor=\"\n let message of messages;\n let i = index;\n let isFirst = first;\n let isLast = last;\n trackBy: trackByMessageId\n \"\n >\n <ng-container *ngIf=\"isFirst\">\n <ng-container\n *ngTemplateOutlet=\"\n dateSeparator;\n context: {\n date: message.created_at,\n parsedDate: parseDate(message.created_at)\n }\n \"\n ></ng-container>\n </ng-container>\n <li\n tabindex=\"0\"\n data-testclass=\"message\"\n class=\"str-chat__li str-chat__li--{{ groupStyles[i] }}\"\n id=\"{{ message.id }}\"\n >\n <ng-container\n *ngTemplateOutlet=\"\n messageTemplateContainer;\n context: { message: message, index: i }\n \"\n ></ng-container>\n </li>\n <ng-container\n *ngIf=\"\n (lastReadMessageId === message?.id &&\n direction === 'bottom-to-top') ||\n (direction === 'top-to-bottom' &&\n lastReadMessageId === messages[i + 1]?.id)\n \"\n >\n <li\n *ngIf=\"displayUnreadSeparator\"\n id=\"stream-chat-new-message-indicator\"\n data-testid=\"new-messages-indicator\"\n class=\"str-chat__li str-chat__unread-messages-separator-wrapper\"\n >\n <ng-container\n *ngTemplateOutlet=\"\n customnewMessagesIndicatorTemplate ||\n defaultNewMessagesIndicator;\n context: { unreadCount: unreadCount }\n \"\n ></ng-container>\n </li>\n </ng-container>\n <ng-container *ngIf=\"isNextMessageOnSeparateDate[i]\">\n <ng-container\n *ngTemplateOutlet=\"\n dateSeparator;\n context: {\n date: messages[i + 1].created_at,\n parsedDate: parseDate(messages[i + 1].created_at)\n }\n \"\n ></ng-container>\n </ng-container>\n </ng-container>\n </ng-container>\n <stream-loading-indicator-placeholder\n *ngIf=\"\n ((loadingState === 'loading-bottom' &&\n direction === 'bottom-to-top') ||\n (loadingState === 'loading-top' &&\n direction === 'top-to-bottom')) &&\n displayLoadingIndicator;\n else loadingIndicatorPlaceholder\n \"\n data-testid=\"bottom-loading-indicator\"\n ></stream-loading-indicator-placeholder>\n <ng-template #loadingIndicatorPlaceholder>\n <div class=\"str-chat__loading-indicator-placeholder\"></div>\n </ng-template>\n </ul>\n <ng-template #defaultTypingIndicator let-usersTyping$=\"usersTyping$\">\n <!-- eslint-disable-next-line @angular-eslint/template/no-any -->\n <ng-container *ngIf=\"$any(usersTyping$ | async) as users\">\n <div\n *ngIf=\"users.length > 0\"\n data-testid=\"typing-indicator\"\n class=\"str-chat__typing-indicator str-chat__typing-indicator--typing\"\n >\n <div class=\"str-chat__typing-indicator__dots\">\n <span class=\"str-chat__typing-indicator__dot\"></span>\n <span class=\"str-chat__typing-indicator__dot\"></span>\n <span class=\"str-chat__typing-indicator__dot\"></span>\n </div>\n <div\n data-testid=\"typing-users\"\n class=\"str-chat__typing-indicator__users\"\n >\n {{\n users.length === 1\n ? (\"streamChat.user is typing\"\n | translate: { user: getTypingIndicatorText(users) })\n : (\"streamChat.users are typing\"\n | translate: { users: getTypingIndicatorText(users) })\n }}\n </div>\n </div>\n </ng-container>\n </ng-template>\n <ng-container\n *ngTemplateOutlet=\"\n typingIndicatorTemplate || defaultTypingIndicator;\n context: getTypingIndicatorContext()\n \"\n ></ng-container>\n </div>\n</div>\n<div class=\"str-chat__jump-to-latest-message\">\n <button\n *ngIf=\"isUserScrolled && isJumpToLatestButtonVisible\"\n data-testid=\"scroll-to-latest\"\n class=\"\n str-chat__message-notification-scroll-to-latest\n str-chat__message-notification-scroll-to-latest-right\n str-chat__circle-fab\n \"\n (keyup.enter)=\"jumpToLatestMessage()\"\n (click)=\"jumpToLatestMessage()\"\n >\n <stream-icon\n class=\"str-chat__jump-to-latest-icon str-chat__circle-fab-icon\"\n [icon]=\"direction === 'bottom-to-top' ? 'arrow-down' : 'arrow-up'\"\n ></stream-icon>\n <div\n *ngIf=\"newMessageCountWhileBeingScrolled > 0\"\n class=\"\n str-chat__message-notification\n str-chat__message-notification-scroll-to-latest-unread-count\n str-chat__jump-to-latest-unread-count\n \"\n >\n {{ newMessageCountWhileBeingScrolled }}\n </div>\n </button>\n</div>\n\n<ng-template #messageTemplateContainer let-message=\"message\" let-index=\"index\">\n <ng-template\n #defaultMessageTemplate\n let-messageInput=\"message\"\n let-isLastSentMessage=\"isLastSentMessage\"\n let-enabledMessageActions=\"enabledMessageActions\"\n let-mode=\"mode\"\n let-isHighlighted=\"isHighlighted\"\n let-scroll$=\"scroll$\"\n >\n <stream-message\n [message]=\"messageInput\"\n [isLastSentMessage]=\"isLastSentMessage\"\n [enabledMessageActions]=\"enabledMessageActions\"\n [mode]=\"mode\"\n [isHighlighted]=\"isHighlighted\"\n [scroll$]=\"scroll$\"\n ></stream-message>\n </ng-template>\n <ng-container\n *ngTemplateOutlet=\"\n messageTemplate || defaultMessageTemplate;\n context: {\n message: message,\n isLastSentMessage: !!(\n lastSentMessageId && message?.id === lastSentMessageId\n ),\n enabledMessageActions: enabledMessageActions,\n mode: mode,\n isHighlighted: message?.id === highlightedMessageId,\n scroll$: scroll$\n }\n \"\n ></ng-container>\n</ng-template>\n\n<ng-template #dateSeparator let-date=\"date\" let-parsedDate=\"parsedDate\">\n <ng-container *ngIf=\"displayDateSeparator\">\n <ng-container\n *ngTemplateOutlet=\"\n customDateSeparatorTemplate || defaultDateSeparator;\n context: {\n date: date,\n parsedDate: parsedDate\n }\n \"\n ></ng-container>\n </ng-container>\n\n <ng-template\n #defaultDateSeparator\n let-date=\"date\"\n let-parsedDate=\"parsedDate\"\n >\n <div data-testid=\"date-separator\" class=\"str-chat__date-separator\">\n <hr\n *ngIf=\"\n dateSeparatorTextPos === 'right' || dateSeparatorTextPos === 'center'\n \"\n class=\"str-chat__date-separator-line\"\n />\n <div class=\"str-chat__date-separator-date\">\n {{ parsedDate }}\n </div>\n <hr\n *ngIf=\"\n dateSeparatorTextPos === 'left' || dateSeparatorTextPos === 'center'\n \"\n class=\"str-chat__date-separator-line\"\n />\n </div>\n </ng-template>\n</ng-template>\n\n<ng-template #defaultNewMessagesIndicator let-unreadCount=\"unreadCount\">\n <div class=\"str-chat__unread-messages-separator\">\n <ng-container\n *ngIf=\"\n unreadCount > 0 && !hideUnreadCountForNotificationAndIndicator;\n else noUnreadCount\n \"\n >\n {{\n (unreadCount === 1\n ? \"streamChat.\\{\\{count\\}\\} unread message\"\n : \"streamChat.\\{\\{count\\}\\} unread messages\"\n ) | translate: { count: unreadCount }\n }}\n </ng-container>\n <ng-template #noUnreadCount>\n {{ \"streamChat.Unread messages\" | translate }}\n </ng-template>\n </div>\n</ng-template>\n" }]
|
|
7088
7354
|
}], ctorParameters: function () { return [{ type: ChannelService }, { type: ChatClientService }, { type: CustomTemplatesService }, { type: DateParserService }, { type: i0.NgZone }, { type: i0.ChangeDetectorRef }]; }, propDecorators: { mode: [{
|
|
7089
7355
|
type: Input
|
|
7090
7356
|
}], direction: [{
|
|
@@ -7103,8 +7369,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.4", ngImpor
|
|
|
7103
7369
|
type: Input
|
|
7104
7370
|
}], displayLoadingIndicator: [{
|
|
7105
7371
|
type: Input
|
|
7106
|
-
}], limitNumberOfMessagesInList: [{
|
|
7107
|
-
type: Input
|
|
7108
7372
|
}], scrollContainer: [{
|
|
7109
7373
|
type: ViewChild,
|
|
7110
7374
|
args: ['scrollContainer']
|
|
@@ -7351,5 +7615,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.4", ngImpor
|
|
|
7351
7615
|
* Generated bundle index. Do not edit.
|
|
7352
7616
|
*/
|
|
7353
7617
|
|
|
7354
|
-
export { AttachmentConfigurationService, AttachmentListComponent, AttachmentPreviewListComponent, AttachmentService, AutocompleteTextareaComponent, AvatarComponent, AvatarPlaceholderComponent, ChannelComponent, ChannelHeaderComponent, ChannelListComponent, ChannelPreviewComponent, ChannelQuery, ChannelService, ChatClientService, CustomTemplatesService, DateParserService, EmojiInputService, IconComponent, IconPlaceholderComponent, LoadingIndicatorComponent, LoadingIndicatorPlaceholderComponent, MessageActionsBoxComponent, MessageActionsService, MessageBouncePromptComponent, MessageComponent, MessageInputComponent, MessageInputConfigService, MessageListComponent, MessageReactionsComponent, MessageReactionsSelectorComponent, MessageReactionsService, MessageService, ModalComponent, NotificationComponent, NotificationListComponent, NotificationService, StreamAutocompleteTextareaModule, StreamAvatarModule, StreamChatModule, StreamI18nService, StreamTextareaModule, TextareaComponent, TextareaDirective, ThemeService, ThreadComponent, TransliterationService, VoiceRecordingComponent, VoiceRecordingWavebarComponent, createMessagePreview, getChannelDisplayText, getGroupStyles, getMessageTranslation, getReadBy, isImageAttachment, isImageFile, isOnSeparateDate, listUsers, parseDate, textareaInjectionToken };
|
|
7618
|
+
export { AttachmentConfigurationService, AttachmentListComponent, AttachmentPreviewListComponent, AttachmentService, AutocompleteTextareaComponent, AvatarComponent, AvatarPlaceholderComponent, ChannelComponent, ChannelHeaderComponent, ChannelListComponent, ChannelPreviewComponent, ChannelQuery, ChannelService, ChatClientService, CustomTemplatesService, DateParserService, EmojiInputService, IconComponent, IconPlaceholderComponent, LoadingIndicatorComponent, LoadingIndicatorPlaceholderComponent, MessageActionsBoxComponent, MessageActionsService, MessageBouncePromptComponent, MessageComponent, MessageInputComponent, MessageInputConfigService, MessageListComponent, MessageReactionsComponent, MessageReactionsSelectorComponent, MessageReactionsService, MessageService, ModalComponent, NotificationComponent, NotificationListComponent, NotificationService, StreamAutocompleteTextareaModule, StreamAvatarModule, StreamChatModule, StreamI18nService, StreamTextareaModule, TextareaComponent, TextareaDirective, ThemeService, ThreadComponent, TransliterationService, VirtualizedListService, VirtualizedMessageListService, VoiceRecordingComponent, VoiceRecordingWavebarComponent, createMessagePreview, getChannelDisplayText, getGroupStyles, getMessageTranslation, getReadBy, isImageAttachment, isImageFile, isOnSeparateDate, listUsers, parseDate, textareaInjectionToken };
|
|
7355
7619
|
//# sourceMappingURL=stream-chat-angular.mjs.map
|