stream-chat 8.14.5 → 8.16.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/dist/browser.es.js +1703 -1123
- package/dist/browser.es.js.map +1 -1
- package/dist/browser.full-bundle.min.js +1 -1
- package/dist/browser.full-bundle.min.js.map +1 -1
- package/dist/browser.js +1704 -1122
- package/dist/browser.js.map +1 -1
- package/dist/index.es.js +1703 -1123
- package/dist/index.es.js.map +1 -1
- package/dist/index.js +1704 -1122
- package/dist/index.js.map +1 -1
- package/dist/types/channel.d.ts +6 -2
- package/dist/types/channel.d.ts.map +1 -1
- package/dist/types/channel_state.d.ts +1 -0
- package/dist/types/channel_state.d.ts.map +1 -1
- package/dist/types/client.d.ts +119 -25
- package/dist/types/client.d.ts.map +1 -1
- package/dist/types/events.d.ts +2 -0
- package/dist/types/events.d.ts.map +1 -1
- package/dist/types/index.d.ts +2 -1
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/thread.d.ts +28 -0
- package/dist/types/thread.d.ts.map +1 -0
- package/dist/types/types.d.ts +99 -20
- package/dist/types/types.d.ts.map +1 -1
- package/dist/types/utils.d.ts +10 -1
- package/dist/types/utils.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/channel.ts +32 -18
- package/src/channel_state.ts +9 -59
- package/src/client.ts +218 -43
- package/src/events.ts +2 -0
- package/src/index.ts +2 -1
- package/src/thread.ts +116 -0
- package/src/types.ts +119 -21
- package/src/utils.ts +101 -1
package/src/thread.ts
ADDED
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { StreamChat } from './client';
|
|
2
|
+
import {
|
|
3
|
+
DefaultGenerics,
|
|
4
|
+
ExtendableGenerics,
|
|
5
|
+
MessageResponse,
|
|
6
|
+
ThreadResponse,
|
|
7
|
+
ChannelResponse,
|
|
8
|
+
FormatMessageResponse,
|
|
9
|
+
ReactionResponse,
|
|
10
|
+
UserResponse,
|
|
11
|
+
} from './types';
|
|
12
|
+
import { addToMessageList, formatMessage } from './utils';
|
|
13
|
+
|
|
14
|
+
type ThreadReadStatus<StreamChatGenerics extends ExtendableGenerics = DefaultGenerics> = Record<
|
|
15
|
+
string,
|
|
16
|
+
{
|
|
17
|
+
last_read: Date;
|
|
18
|
+
last_read_message_id: string;
|
|
19
|
+
unread_messages: number;
|
|
20
|
+
user: UserResponse<StreamChatGenerics>;
|
|
21
|
+
}
|
|
22
|
+
>;
|
|
23
|
+
|
|
24
|
+
export class Thread<StreamChatGenerics extends ExtendableGenerics = DefaultGenerics> {
|
|
25
|
+
id: string;
|
|
26
|
+
latestReplies: FormatMessageResponse<StreamChatGenerics>[] = [];
|
|
27
|
+
participants: ThreadResponse['thread_participants'] = [];
|
|
28
|
+
message: FormatMessageResponse<StreamChatGenerics>;
|
|
29
|
+
channel: ChannelResponse<StreamChatGenerics>;
|
|
30
|
+
_channel: ReturnType<StreamChat<StreamChatGenerics>['channel']>;
|
|
31
|
+
replyCount = 0;
|
|
32
|
+
_client: StreamChat<StreamChatGenerics>;
|
|
33
|
+
read: ThreadReadStatus<StreamChatGenerics> = {};
|
|
34
|
+
|
|
35
|
+
constructor(client: StreamChat<StreamChatGenerics>, t: ThreadResponse<StreamChatGenerics>) {
|
|
36
|
+
this.id = t.parent_message.id;
|
|
37
|
+
this.message = formatMessage(t.parent_message);
|
|
38
|
+
this.latestReplies = t.latest_replies.map(formatMessage);
|
|
39
|
+
this.participants = t.thread_participants;
|
|
40
|
+
this.replyCount = t.reply_count;
|
|
41
|
+
this.channel = t.channel;
|
|
42
|
+
this._channel = client.channel(t.channel.type, t.channel.id);
|
|
43
|
+
this._client = client;
|
|
44
|
+
for (const r of t.read) {
|
|
45
|
+
this.read[r.user.id] = {
|
|
46
|
+
...r,
|
|
47
|
+
last_read: new Date(r.last_read),
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
getClient(): StreamChat<StreamChatGenerics> {
|
|
53
|
+
return this._client;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
addReply(message: MessageResponse<StreamChatGenerics>) {
|
|
57
|
+
this.latestReplies = addToMessageList(this.latestReplies, formatMessage(message));
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
updateReply(message: MessageResponse<StreamChatGenerics>) {
|
|
61
|
+
this.latestReplies = this.latestReplies.map((m) => {
|
|
62
|
+
if (m.id === message.id) {
|
|
63
|
+
return formatMessage(message);
|
|
64
|
+
}
|
|
65
|
+
return m;
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
updateMessageOrReplyIfExists(message: MessageResponse<StreamChatGenerics>) {
|
|
70
|
+
if (!message.parent_id && message.id !== this.message.id) {
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
if (message.parent_id && message.parent_id !== this.message.id) {
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
if (message.parent_id && message.parent_id === this.message.id) {
|
|
79
|
+
this.updateReply(message);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
if (!message.parent_id && message.id === this.message.id) {
|
|
83
|
+
this.message = formatMessage(message);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
addReaction(
|
|
88
|
+
reaction: ReactionResponse<StreamChatGenerics>,
|
|
89
|
+
message?: MessageResponse<StreamChatGenerics>,
|
|
90
|
+
enforce_unique?: boolean,
|
|
91
|
+
) {
|
|
92
|
+
if (!message) return;
|
|
93
|
+
|
|
94
|
+
this.latestReplies = this.latestReplies.map((m) => {
|
|
95
|
+
if (m.id === message.id) {
|
|
96
|
+
return formatMessage(
|
|
97
|
+
this._channel.state.addReaction(reaction, message, enforce_unique) as MessageResponse<StreamChatGenerics>,
|
|
98
|
+
);
|
|
99
|
+
}
|
|
100
|
+
return m;
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
removeReaction(reaction: ReactionResponse<StreamChatGenerics>, message?: MessageResponse<StreamChatGenerics>) {
|
|
105
|
+
if (!message) return;
|
|
106
|
+
|
|
107
|
+
this.latestReplies = this.latestReplies.map((m) => {
|
|
108
|
+
if (m.id === message.id) {
|
|
109
|
+
return formatMessage(
|
|
110
|
+
this._channel.state.removeReaction(reaction, message) as MessageResponse<StreamChatGenerics>,
|
|
111
|
+
);
|
|
112
|
+
}
|
|
113
|
+
return m;
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
}
|
package/src/types.ts
CHANGED
|
@@ -114,6 +114,10 @@ export type AppSettingsAPIResponse<StreamChatGenerics extends ExtendableGenerics
|
|
|
114
114
|
campaign_enabled?: boolean;
|
|
115
115
|
cdn_expiration_seconds?: number;
|
|
116
116
|
custom_action_handler_url?: string;
|
|
117
|
+
datadog_info?: {
|
|
118
|
+
api_key: string;
|
|
119
|
+
site: string;
|
|
120
|
+
};
|
|
117
121
|
disable_auth_checks?: boolean;
|
|
118
122
|
disable_permissions_checks?: boolean;
|
|
119
123
|
enforce_unique_usernames?: 'no' | 'app' | 'team';
|
|
@@ -247,6 +251,7 @@ export type BannedUsersResponse<StreamChatGenerics extends ExtendableGenerics =
|
|
|
247
251
|
|
|
248
252
|
export type BlockListResponse = BlockList & {
|
|
249
253
|
created_at?: string;
|
|
254
|
+
type?: string;
|
|
250
255
|
updated_at?: string;
|
|
251
256
|
};
|
|
252
257
|
|
|
@@ -473,6 +478,58 @@ export type GetMessageAPIResponse<
|
|
|
473
478
|
StreamChatGenerics extends ExtendableGenerics = DefaultGenerics
|
|
474
479
|
> = SendMessageAPIResponse<StreamChatGenerics>;
|
|
475
480
|
|
|
481
|
+
export type ThreadResponse<StreamChatGenerics extends ExtendableGenerics = DefaultGenerics> = {
|
|
482
|
+
channel: ChannelResponse<StreamChatGenerics>;
|
|
483
|
+
channel_cid: string;
|
|
484
|
+
created_at: string;
|
|
485
|
+
deleted_at: string;
|
|
486
|
+
latest_replies: MessageResponse<StreamChatGenerics>[];
|
|
487
|
+
parent_message: MessageResponse<StreamChatGenerics>;
|
|
488
|
+
parent_message_id: string;
|
|
489
|
+
read: {
|
|
490
|
+
last_read: string;
|
|
491
|
+
last_read_message_id: string;
|
|
492
|
+
unread_messages: number;
|
|
493
|
+
user: UserResponse<StreamChatGenerics>;
|
|
494
|
+
}[];
|
|
495
|
+
reply_count: number;
|
|
496
|
+
thread_participants: {
|
|
497
|
+
created_at: string;
|
|
498
|
+
user: UserResponse<StreamChatGenerics>;
|
|
499
|
+
}[];
|
|
500
|
+
title: string;
|
|
501
|
+
updated_at: string;
|
|
502
|
+
};
|
|
503
|
+
|
|
504
|
+
// TODO: Figure out a way to strongly type set and unset.
|
|
505
|
+
export type PartialThreadUpdate = {
|
|
506
|
+
set?: Partial<Record<string, unknown>>;
|
|
507
|
+
unset?: Partial<Record<string, unknown>>;
|
|
508
|
+
};
|
|
509
|
+
|
|
510
|
+
export type QueryThreadsOptions = {
|
|
511
|
+
limit?: number;
|
|
512
|
+
next?: string;
|
|
513
|
+
participant_limit?: number;
|
|
514
|
+
reply_limit?: number;
|
|
515
|
+
watch?: boolean;
|
|
516
|
+
};
|
|
517
|
+
|
|
518
|
+
export type QueryThreadsAPIResponse<StreamChatGenerics extends ExtendableGenerics = DefaultGenerics> = APIResponse & {
|
|
519
|
+
threads: ThreadResponse<StreamChatGenerics>[];
|
|
520
|
+
next?: string;
|
|
521
|
+
};
|
|
522
|
+
|
|
523
|
+
export type GetThreadOptions = {
|
|
524
|
+
participant_limit?: number;
|
|
525
|
+
reply_limit?: number;
|
|
526
|
+
watch?: boolean;
|
|
527
|
+
};
|
|
528
|
+
|
|
529
|
+
export type GetThreadAPIResponse<StreamChatGenerics extends ExtendableGenerics = DefaultGenerics> = APIResponse & {
|
|
530
|
+
thread: ThreadResponse<StreamChatGenerics>;
|
|
531
|
+
};
|
|
532
|
+
|
|
476
533
|
export type GetMultipleMessagesAPIResponse<
|
|
477
534
|
StreamChatGenerics extends ExtendableGenerics = DefaultGenerics
|
|
478
535
|
> = APIResponse & {
|
|
@@ -505,7 +562,18 @@ export type GetUnreadCountAPIResponse = APIResponse & {
|
|
|
505
562
|
last_read: string;
|
|
506
563
|
unread_count: number;
|
|
507
564
|
}[];
|
|
565
|
+
threads: {
|
|
566
|
+
last_read: string;
|
|
567
|
+
last_read_message_id: string;
|
|
568
|
+
parent_message_id: string;
|
|
569
|
+
unread_count: number;
|
|
570
|
+
}[];
|
|
508
571
|
total_unread_count: number;
|
|
572
|
+
total_unread_threads_count: number;
|
|
573
|
+
};
|
|
574
|
+
|
|
575
|
+
export type GetUnreadCountBatchAPIResponse = APIResponse & {
|
|
576
|
+
counts_by_user: { [userId: string]: GetUnreadCountAPIResponse };
|
|
509
577
|
};
|
|
510
578
|
|
|
511
579
|
export type ListChannelResponse<StreamChatGenerics extends ExtendableGenerics = DefaultGenerics> = APIResponse & {
|
|
@@ -558,6 +626,7 @@ export type MessageResponseBase<
|
|
|
558
626
|
};
|
|
559
627
|
latest_reactions?: ReactionResponse<StreamChatGenerics>[];
|
|
560
628
|
mentioned_users?: UserResponse<StreamChatGenerics>[];
|
|
629
|
+
moderation_details?: ModerationDetailsResponse;
|
|
561
630
|
own_reactions?: ReactionResponse<StreamChatGenerics>[] | null;
|
|
562
631
|
pin_expires?: string | null;
|
|
563
632
|
pinned_at?: string | null;
|
|
@@ -571,6 +640,18 @@ export type MessageResponseBase<
|
|
|
571
640
|
updated_at?: string;
|
|
572
641
|
};
|
|
573
642
|
|
|
643
|
+
export type ModerationDetailsResponse = {
|
|
644
|
+
action: 'MESSAGE_RESPONSE_ACTION_BOUNCE' | (string & {});
|
|
645
|
+
error_msg: string;
|
|
646
|
+
harms: ModerationHarmResponse[];
|
|
647
|
+
original_text: string;
|
|
648
|
+
};
|
|
649
|
+
|
|
650
|
+
export type ModerationHarmResponse = {
|
|
651
|
+
name: string;
|
|
652
|
+
phrase_list_ids: number[];
|
|
653
|
+
};
|
|
654
|
+
|
|
574
655
|
export type MuteResponse<StreamChatGenerics extends ExtendableGenerics = DefaultGenerics> = {
|
|
575
656
|
user: UserResponse<StreamChatGenerics>;
|
|
576
657
|
created_at?: string;
|
|
@@ -871,6 +952,7 @@ export type MarkChannelsReadOptions<StreamChatGenerics extends ExtendableGeneric
|
|
|
871
952
|
export type MarkReadOptions<StreamChatGenerics extends ExtendableGenerics = DefaultGenerics> = {
|
|
872
953
|
client_id?: string;
|
|
873
954
|
connection_id?: string;
|
|
955
|
+
thread_id?: string;
|
|
874
956
|
user?: UserResponse<StreamChatGenerics>;
|
|
875
957
|
user_id?: string;
|
|
876
958
|
};
|
|
@@ -1055,8 +1137,13 @@ export type Event<StreamChatGenerics extends ExtendableGenerics = DefaultGeneric
|
|
|
1055
1137
|
cid?: string;
|
|
1056
1138
|
clear_history?: boolean;
|
|
1057
1139
|
connection_id?: string;
|
|
1140
|
+
// event creation timestamp, format Date ISO string
|
|
1058
1141
|
created_at?: string;
|
|
1142
|
+
// id of the message that was marked as unread - all the following messages are considered unread. (notification.mark_unread)
|
|
1143
|
+
first_unread_message_id?: string;
|
|
1059
1144
|
hard_delete?: boolean;
|
|
1145
|
+
// creation date of a message with last_read_message_id, formatted as Date ISO string
|
|
1146
|
+
last_read_at?: string;
|
|
1060
1147
|
last_read_message_id?: string;
|
|
1061
1148
|
mark_messages_deleted?: boolean;
|
|
1062
1149
|
me?: OwnUserResponse<StreamChatGenerics>;
|
|
@@ -1072,9 +1159,15 @@ export type Event<StreamChatGenerics extends ExtendableGenerics = DefaultGeneric
|
|
|
1072
1159
|
reaction?: ReactionResponse<StreamChatGenerics>;
|
|
1073
1160
|
received_at?: string | Date;
|
|
1074
1161
|
team?: string;
|
|
1162
|
+
thread?: ThreadResponse<StreamChatGenerics>;
|
|
1163
|
+
// @deprecated number of all unread messages across all current user's unread channels, equals unread_count
|
|
1075
1164
|
total_unread_count?: number;
|
|
1165
|
+
// number of all current user's channels with at least one unread message including the channel in this event
|
|
1076
1166
|
unread_channels?: number;
|
|
1167
|
+
// number of all unread messages across all current user's unread channels
|
|
1077
1168
|
unread_count?: number;
|
|
1169
|
+
// number of unread messages in the channel from this event (notification.mark_unread)
|
|
1170
|
+
unread_messages?: number;
|
|
1078
1171
|
user?: UserResponse<StreamChatGenerics>;
|
|
1079
1172
|
user_id?: string;
|
|
1080
1173
|
watcher_count?: number;
|
|
@@ -2390,22 +2483,43 @@ export type DeleteUserOptions = {
|
|
|
2390
2483
|
user?: DeleteType;
|
|
2391
2484
|
};
|
|
2392
2485
|
|
|
2486
|
+
export type SegmentType = 'channel' | 'user';
|
|
2487
|
+
|
|
2393
2488
|
export type SegmentData = {
|
|
2394
2489
|
description: string;
|
|
2395
2490
|
filter: {};
|
|
2396
|
-
name: string;
|
|
2397
|
-
type: 'channel' | 'user';
|
|
2398
2491
|
};
|
|
2399
2492
|
|
|
2400
2493
|
export type Segment = {
|
|
2401
2494
|
created_at: string;
|
|
2495
|
+
deleted_at: string;
|
|
2402
2496
|
id: string;
|
|
2403
|
-
|
|
2497
|
+
locked: boolean;
|
|
2498
|
+
name: string;
|
|
2404
2499
|
size: number;
|
|
2405
|
-
|
|
2500
|
+
type: SegmentType;
|
|
2406
2501
|
updated_at: string;
|
|
2407
2502
|
} & SegmentData;
|
|
2408
2503
|
|
|
2504
|
+
export type UpdateSegmentData = {
|
|
2505
|
+
name: string;
|
|
2506
|
+
} & SegmentData;
|
|
2507
|
+
|
|
2508
|
+
export type SortParam = {
|
|
2509
|
+
field: string;
|
|
2510
|
+
direction?: AscDesc;
|
|
2511
|
+
};
|
|
2512
|
+
|
|
2513
|
+
export type Pager = {
|
|
2514
|
+
limit?: number;
|
|
2515
|
+
next?: string;
|
|
2516
|
+
prev?: string;
|
|
2517
|
+
};
|
|
2518
|
+
|
|
2519
|
+
export type QuerySegmentsOptions = {
|
|
2520
|
+
sort?: SortParam[];
|
|
2521
|
+
} & Pager;
|
|
2522
|
+
|
|
2409
2523
|
export type CampaignSortField = {
|
|
2410
2524
|
field: string;
|
|
2411
2525
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
@@ -2423,12 +2537,9 @@ export type CampaignQueryOptions = {
|
|
|
2423
2537
|
};
|
|
2424
2538
|
|
|
2425
2539
|
export type SegmentQueryOptions = CampaignQueryOptions;
|
|
2426
|
-
export type RecipientQueryOptions = CampaignQueryOptions;
|
|
2427
2540
|
|
|
2428
2541
|
// TODO: add better typing
|
|
2429
|
-
export type SegmentFilters = {};
|
|
2430
2542
|
export type CampaignFilters = {};
|
|
2431
|
-
export type RecipientFilters = {};
|
|
2432
2543
|
|
|
2433
2544
|
export type CampaignData = {
|
|
2434
2545
|
attachments: Attachment[];
|
|
@@ -2469,20 +2580,7 @@ export type TestCampaignResponse = {
|
|
|
2469
2580
|
results?: Record<string, string>;
|
|
2470
2581
|
};
|
|
2471
2582
|
|
|
2472
|
-
export type DeleteCampaignOptions = {
|
|
2473
|
-
recipients?: boolean;
|
|
2474
|
-
};
|
|
2475
|
-
|
|
2476
|
-
export type Recipient = {
|
|
2477
|
-
campaign_id: string;
|
|
2478
|
-
channel_cid: string;
|
|
2479
|
-
created_at: string;
|
|
2480
|
-
status: 'pending' | 'sent' | 'failed';
|
|
2481
|
-
updated_at: string;
|
|
2482
|
-
details?: string;
|
|
2483
|
-
message_id?: string;
|
|
2484
|
-
receiver_id?: string;
|
|
2485
|
-
};
|
|
2583
|
+
export type DeleteCampaignOptions = {};
|
|
2486
2584
|
|
|
2487
2585
|
export type TaskStatus = {
|
|
2488
2586
|
created_at: string;
|
package/src/utils.ts
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
import FormData from 'form-data';
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
AscDesc,
|
|
4
|
+
ExtendableGenerics,
|
|
5
|
+
DefaultGenerics,
|
|
6
|
+
OwnUserBase,
|
|
7
|
+
OwnUserResponse,
|
|
8
|
+
UserResponse,
|
|
9
|
+
MessageResponse,
|
|
10
|
+
FormatMessageResponse,
|
|
11
|
+
} from './types';
|
|
3
12
|
import { AxiosRequestConfig } from 'axios';
|
|
4
13
|
|
|
5
14
|
/**
|
|
@@ -263,3 +272,94 @@ export const axiosParamsSerializer: AxiosRequestConfig['paramsSerializer'] = (pa
|
|
|
263
272
|
|
|
264
273
|
return newParams.join('&');
|
|
265
274
|
};
|
|
275
|
+
|
|
276
|
+
/**
|
|
277
|
+
* formatMessage - Takes the message object. Parses the dates, sets __html
|
|
278
|
+
* and sets the status to received if missing. Returns a message object
|
|
279
|
+
*
|
|
280
|
+
* @param {MessageResponse<StreamChatGenerics>} message a message object
|
|
281
|
+
*
|
|
282
|
+
*/
|
|
283
|
+
export function formatMessage<StreamChatGenerics extends ExtendableGenerics = DefaultGenerics>(
|
|
284
|
+
message: MessageResponse<StreamChatGenerics>,
|
|
285
|
+
): FormatMessageResponse<StreamChatGenerics> {
|
|
286
|
+
return {
|
|
287
|
+
...message,
|
|
288
|
+
/**
|
|
289
|
+
* @deprecated please use `html`
|
|
290
|
+
*/
|
|
291
|
+
__html: message.html,
|
|
292
|
+
// parse the date..
|
|
293
|
+
pinned_at: message.pinned_at ? new Date(message.pinned_at) : null,
|
|
294
|
+
created_at: message.created_at ? new Date(message.created_at) : new Date(),
|
|
295
|
+
updated_at: message.updated_at ? new Date(message.updated_at) : new Date(),
|
|
296
|
+
status: message.status || 'received',
|
|
297
|
+
};
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
export function addToMessageList<StreamChatGenerics extends ExtendableGenerics = DefaultGenerics>(
|
|
301
|
+
messages: Array<FormatMessageResponse<StreamChatGenerics>>,
|
|
302
|
+
message: FormatMessageResponse<StreamChatGenerics>,
|
|
303
|
+
timestampChanged = false,
|
|
304
|
+
sortBy: 'pinned_at' | 'created_at' = 'created_at',
|
|
305
|
+
addIfDoesNotExist = true,
|
|
306
|
+
) {
|
|
307
|
+
const addMessageToList = addIfDoesNotExist || timestampChanged;
|
|
308
|
+
let messageArr = messages;
|
|
309
|
+
|
|
310
|
+
// if created_at has changed, message should be filtered and re-inserted in correct order
|
|
311
|
+
// slow op but usually this only happens for a message inserted to state before actual response with correct timestamp
|
|
312
|
+
if (timestampChanged) {
|
|
313
|
+
messageArr = messageArr.filter((msg) => !(msg.id && message.id === msg.id));
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
// Get array length after filtering
|
|
317
|
+
const messageArrayLength = messageArr.length;
|
|
318
|
+
|
|
319
|
+
// for empty list just concat and return unless it's an update or deletion
|
|
320
|
+
if (messageArrayLength === 0 && addMessageToList) {
|
|
321
|
+
return messageArr.concat(message);
|
|
322
|
+
} else if (messageArrayLength === 0) {
|
|
323
|
+
return [...messageArr];
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
const messageTime = (message[sortBy] as Date).getTime();
|
|
327
|
+
const messageIsNewest = (messageArr[messageArrayLength - 1][sortBy] as Date).getTime() < messageTime;
|
|
328
|
+
|
|
329
|
+
// if message is newer than last item in the list concat and return unless it's an update or deletion
|
|
330
|
+
if (messageIsNewest && addMessageToList) {
|
|
331
|
+
return messageArr.concat(message);
|
|
332
|
+
} else if (messageIsNewest) {
|
|
333
|
+
return [...messageArr];
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
// find the closest index to push the new message
|
|
337
|
+
let left = 0;
|
|
338
|
+
let middle = 0;
|
|
339
|
+
let right = messageArrayLength - 1;
|
|
340
|
+
while (left <= right) {
|
|
341
|
+
middle = Math.floor((right + left) / 2);
|
|
342
|
+
if ((messageArr[middle][sortBy] as Date).getTime() <= messageTime) left = middle + 1;
|
|
343
|
+
else right = middle - 1;
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
// message already exists and not filtered due to timestampChanged, update and return
|
|
347
|
+
if (!timestampChanged && message.id) {
|
|
348
|
+
if (messageArr[left] && message.id === messageArr[left].id) {
|
|
349
|
+
messageArr[left] = message;
|
|
350
|
+
return [...messageArr];
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
if (messageArr[left - 1] && message.id === messageArr[left - 1].id) {
|
|
354
|
+
messageArr[left - 1] = message;
|
|
355
|
+
return [...messageArr];
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
// Do not add updated or deleted messages to the list if they do not already exist
|
|
360
|
+
// or have a timestamp change.
|
|
361
|
+
if (addMessageToList) {
|
|
362
|
+
messageArr.splice(left, 0, message);
|
|
363
|
+
}
|
|
364
|
+
return [...messageArr];
|
|
365
|
+
}
|