stream-chat 8.15.0 → 8.17.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 +1032 -670
- 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 +1033 -669
- package/dist/browser.js.map +1 -1
- package/dist/index.es.js +1032 -670
- package/dist/index.es.js.map +1 -1
- package/dist/index.js +1033 -669
- 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.map +1 -1
- package/dist/types/client.d.ts +41 -27
- package/dist/types/client.d.ts.map +1 -1
- package/dist/types/events.d.ts +1 -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 +57 -2
- 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 +3 -7
- package/src/channel.ts +18 -4
- package/src/channel_state.ts +2 -58
- package/src/client.ts +104 -0
- package/src/events.ts +1 -0
- package/src/index.ts +2 -1
- package/src/thread.ts +116 -0
- package/src/types.ts +64 -2
- package/src/utils.ts +101 -1
package/src/client.ts
CHANGED
|
@@ -95,6 +95,7 @@ import {
|
|
|
95
95
|
GetImportResponse,
|
|
96
96
|
GetMessageAPIResponse,
|
|
97
97
|
GetRateLimitsResponse,
|
|
98
|
+
QueryThreadsAPIResponse,
|
|
98
99
|
GetUnreadCountAPIResponse,
|
|
99
100
|
GetUnreadCountBatchAPIResponse,
|
|
100
101
|
ListChannelResponse,
|
|
@@ -163,8 +164,13 @@ import {
|
|
|
163
164
|
UserOptions,
|
|
164
165
|
UserResponse,
|
|
165
166
|
UserSort,
|
|
167
|
+
GetThreadAPIResponse,
|
|
168
|
+
PartialThreadUpdate,
|
|
169
|
+
QueryThreadsOptions,
|
|
170
|
+
GetThreadOptions,
|
|
166
171
|
} from './types';
|
|
167
172
|
import { InsightMetrics, postInsights } from './insights';
|
|
173
|
+
import { Thread } from './thread';
|
|
168
174
|
|
|
169
175
|
function isString(x: unknown): x is string {
|
|
170
176
|
return typeof x === 'string' || x instanceof String;
|
|
@@ -2595,6 +2601,103 @@ export class StreamChat<StreamChatGenerics extends ExtendableGenerics = DefaultG
|
|
|
2595
2601
|
);
|
|
2596
2602
|
}
|
|
2597
2603
|
|
|
2604
|
+
/**
|
|
2605
|
+
* queryThreads - returns the list of threads of current user.
|
|
2606
|
+
*
|
|
2607
|
+
* @param {QueryThreadsOptions} options Options object for pagination and limiting the participants and replies.
|
|
2608
|
+
* @param {number} options.limit Limits the number of threads to be returned.
|
|
2609
|
+
* @param {boolean} options.watch Subscribes the user to the channels of the threads.
|
|
2610
|
+
* @param {number} options.participant_limit Limits the number of participants returned per threads.
|
|
2611
|
+
* @param {number} options.reply_limit Limits the number of replies returned per threads.
|
|
2612
|
+
*
|
|
2613
|
+
* @returns {{ threads: Thread<StreamChatGenerics>[], next: string }} Returns the list of threads and the next cursor.
|
|
2614
|
+
*/
|
|
2615
|
+
async queryThreads(options?: QueryThreadsOptions) {
|
|
2616
|
+
const opts = {
|
|
2617
|
+
limit: 10,
|
|
2618
|
+
participant_limit: 10,
|
|
2619
|
+
reply_limit: 3,
|
|
2620
|
+
watch: true,
|
|
2621
|
+
...options,
|
|
2622
|
+
};
|
|
2623
|
+
|
|
2624
|
+
const res = await this.post<QueryThreadsAPIResponse<StreamChatGenerics>>(this.baseURL + `/threads`, opts);
|
|
2625
|
+
|
|
2626
|
+
return {
|
|
2627
|
+
threads: res.threads.map((thread) => new Thread(this, thread)),
|
|
2628
|
+
next: res.next,
|
|
2629
|
+
};
|
|
2630
|
+
}
|
|
2631
|
+
|
|
2632
|
+
/**
|
|
2633
|
+
* getThread - returns the thread of a message by its id.
|
|
2634
|
+
*
|
|
2635
|
+
* @param {string} messageId The message id
|
|
2636
|
+
* @param {GetThreadOptions} options Options object for pagination and limiting the participants and replies.
|
|
2637
|
+
* @param {boolean} options.watch Subscribes the user to the channel of the thread.
|
|
2638
|
+
* @param {number} options.participant_limit Limits the number of participants returned per threads.
|
|
2639
|
+
* @param {number} options.reply_limit Limits the number of replies returned per threads.
|
|
2640
|
+
*
|
|
2641
|
+
* @returns {Thread<StreamChatGenerics>} Returns the thread.
|
|
2642
|
+
*/
|
|
2643
|
+
async getThread(messageId: string, options: GetThreadOptions = {}) {
|
|
2644
|
+
if (!messageId) {
|
|
2645
|
+
throw Error('Please specify the message id when calling partialUpdateThread');
|
|
2646
|
+
}
|
|
2647
|
+
|
|
2648
|
+
const opts = {
|
|
2649
|
+
participant_limit: 100,
|
|
2650
|
+
reply_limit: 3,
|
|
2651
|
+
watch: true,
|
|
2652
|
+
...options,
|
|
2653
|
+
};
|
|
2654
|
+
|
|
2655
|
+
const res = await this.get<GetThreadAPIResponse<StreamChatGenerics>>(this.baseURL + `/threads/${messageId}`, opts);
|
|
2656
|
+
|
|
2657
|
+
return new Thread<StreamChatGenerics>(this, res.thread);
|
|
2658
|
+
}
|
|
2659
|
+
|
|
2660
|
+
/**
|
|
2661
|
+
* partialUpdateThread - updates the given thread
|
|
2662
|
+
*
|
|
2663
|
+
* @param {string} messageId The id of the thread message which needs to be updated.
|
|
2664
|
+
* @param {PartialThreadUpdate} partialThreadObject should contain "set" or "unset" params for any of the thread's non-reserved fields.
|
|
2665
|
+
*
|
|
2666
|
+
* @returns {GetThreadAPIResponse<StreamChatGenerics>} Returns the updated thread.
|
|
2667
|
+
*/
|
|
2668
|
+
async partialUpdateThread(messageId: string, partialThreadObject: PartialThreadUpdate) {
|
|
2669
|
+
if (!messageId) {
|
|
2670
|
+
throw Error('Please specify the message id when calling partialUpdateThread');
|
|
2671
|
+
}
|
|
2672
|
+
|
|
2673
|
+
// check for reserved fields from ThreadResponse type within partialThreadObject's set and unset.
|
|
2674
|
+
// Throw error if any of the reserved field is found.
|
|
2675
|
+
const reservedThreadFields = [
|
|
2676
|
+
'created_at',
|
|
2677
|
+
'id',
|
|
2678
|
+
'last_message_at',
|
|
2679
|
+
'type',
|
|
2680
|
+
'updated_at',
|
|
2681
|
+
'user',
|
|
2682
|
+
'reply_count',
|
|
2683
|
+
'participants',
|
|
2684
|
+
'channel',
|
|
2685
|
+
];
|
|
2686
|
+
|
|
2687
|
+
for (const key in { ...partialThreadObject.set, ...partialThreadObject.unset }) {
|
|
2688
|
+
if (reservedThreadFields.includes(key)) {
|
|
2689
|
+
throw Error(
|
|
2690
|
+
`You cannot set ${key} field on Thread object. ${key} is reserved for server-side use. Please omit ${key} from your set object.`,
|
|
2691
|
+
);
|
|
2692
|
+
}
|
|
2693
|
+
}
|
|
2694
|
+
|
|
2695
|
+
return await this.patch<GetThreadAPIResponse<StreamChatGenerics>>(
|
|
2696
|
+
this.baseURL + `/threads/${messageId}`,
|
|
2697
|
+
partialThreadObject,
|
|
2698
|
+
);
|
|
2699
|
+
}
|
|
2700
|
+
|
|
2598
2701
|
getUserAgent() {
|
|
2599
2702
|
return (
|
|
2600
2703
|
this.userAgent || `stream-chat-javascript-client-${this.node ? 'node' : 'browser'}-${process.env.PKG_VERSION}`
|
|
@@ -2938,6 +3041,7 @@ export class StreamChat<StreamChatGenerics extends ExtendableGenerics = DefaultG
|
|
|
2938
3041
|
async querySegments(filter: {}, options: QuerySegmentsOptions = {}) {
|
|
2939
3042
|
return await this.get<{
|
|
2940
3043
|
segments: Segment[];
|
|
3044
|
+
next?: string;
|
|
2941
3045
|
}>(this.baseURL + `/segments`, {
|
|
2942
3046
|
payload: {
|
|
2943
3047
|
filter,
|
package/src/events.ts
CHANGED
|
@@ -28,6 +28,7 @@ export const EVENT_MAP = {
|
|
|
28
28
|
'notification.message_new': true,
|
|
29
29
|
'notification.mutes_updated': true,
|
|
30
30
|
'notification.removed_from_channel': true,
|
|
31
|
+
'notification.thread_message_new': true,
|
|
31
32
|
'reaction.deleted': true,
|
|
32
33
|
'reaction.new': true,
|
|
33
34
|
'reaction.updated': true,
|
package/src/index.ts
CHANGED
|
@@ -3,6 +3,7 @@ export * from './client';
|
|
|
3
3
|
export * from './client_state';
|
|
4
4
|
export * from './channel';
|
|
5
5
|
export * from './channel_state';
|
|
6
|
+
export * from './thread';
|
|
6
7
|
export * from './connection';
|
|
7
8
|
export * from './events';
|
|
8
9
|
export * from './permissions';
|
|
@@ -10,4 +11,4 @@ export * from './signing';
|
|
|
10
11
|
export * from './token_manager';
|
|
11
12
|
export * from './insights';
|
|
12
13
|
export * from './types';
|
|
13
|
-
export { isOwnUser, chatCodes, logChatPromiseExecution } from './utils';
|
|
14
|
+
export { isOwnUser, chatCodes, logChatPromiseExecution, formatMessage } from './utils';
|
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
|
@@ -478,6 +478,58 @@ export type GetMessageAPIResponse<
|
|
|
478
478
|
StreamChatGenerics extends ExtendableGenerics = DefaultGenerics
|
|
479
479
|
> = SendMessageAPIResponse<StreamChatGenerics>;
|
|
480
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
|
+
|
|
481
533
|
export type GetMultipleMessagesAPIResponse<
|
|
482
534
|
StreamChatGenerics extends ExtendableGenerics = DefaultGenerics
|
|
483
535
|
> = APIResponse & {
|
|
@@ -510,7 +562,14 @@ export type GetUnreadCountAPIResponse = APIResponse & {
|
|
|
510
562
|
last_read: string;
|
|
511
563
|
unread_count: number;
|
|
512
564
|
}[];
|
|
565
|
+
threads: {
|
|
566
|
+
last_read: string;
|
|
567
|
+
last_read_message_id: string;
|
|
568
|
+
parent_message_id: string;
|
|
569
|
+
unread_count: number;
|
|
570
|
+
}[];
|
|
513
571
|
total_unread_count: number;
|
|
572
|
+
total_unread_threads_count: number;
|
|
514
573
|
};
|
|
515
574
|
|
|
516
575
|
export type GetUnreadCountBatchAPIResponse = APIResponse & {
|
|
@@ -893,6 +952,7 @@ export type MarkChannelsReadOptions<StreamChatGenerics extends ExtendableGeneric
|
|
|
893
952
|
export type MarkReadOptions<StreamChatGenerics extends ExtendableGenerics = DefaultGenerics> = {
|
|
894
953
|
client_id?: string;
|
|
895
954
|
connection_id?: string;
|
|
955
|
+
thread_id?: string;
|
|
896
956
|
user?: UserResponse<StreamChatGenerics>;
|
|
897
957
|
user_id?: string;
|
|
898
958
|
};
|
|
@@ -1099,6 +1159,7 @@ export type Event<StreamChatGenerics extends ExtendableGenerics = DefaultGeneric
|
|
|
1099
1159
|
reaction?: ReactionResponse<StreamChatGenerics>;
|
|
1100
1160
|
received_at?: string | Date;
|
|
1101
1161
|
team?: string;
|
|
1162
|
+
thread?: ThreadResponse<StreamChatGenerics>;
|
|
1102
1163
|
// @deprecated number of all unread messages across all current user's unread channels, equals unread_count
|
|
1103
1164
|
total_unread_count?: number;
|
|
1104
1165
|
// number of all current user's channels with at least one unread message including the channel in this event
|
|
@@ -1446,6 +1507,7 @@ export type UserFilters<StreamChatGenerics extends ExtendableGenerics = DefaultG
|
|
|
1446
1507
|
| RequireOnlyOne<{
|
|
1447
1508
|
$contains?: PrimitiveFilter<string>;
|
|
1448
1509
|
$eq?: PrimitiveFilter<UserResponse<StreamChatGenerics>['teams']>;
|
|
1510
|
+
$in?: PrimitiveFilter<UserResponse<StreamChatGenerics>['teams']>;
|
|
1449
1511
|
}>
|
|
1450
1512
|
| PrimitiveFilter<UserResponse<StreamChatGenerics>['teams']>;
|
|
1451
1513
|
username?:
|
|
@@ -2425,8 +2487,8 @@ export type DeleteUserOptions = {
|
|
|
2425
2487
|
export type SegmentType = 'channel' | 'user';
|
|
2426
2488
|
|
|
2427
2489
|
export type SegmentData = {
|
|
2428
|
-
description
|
|
2429
|
-
filter
|
|
2490
|
+
description?: string;
|
|
2491
|
+
filter?: {};
|
|
2430
2492
|
};
|
|
2431
2493
|
|
|
2432
2494
|
export type Segment = {
|
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
|
+
}
|