stream-chat 6.2.0 → 6.3.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.
@@ -6,6 +6,7 @@ import {
6
6
  Event,
7
7
  ExtendableGenerics,
8
8
  DefaultGenerics,
9
+ MessageSetType,
9
10
  MessageResponse,
10
11
  ReactionResponse,
11
12
  UserResponse,
@@ -24,7 +25,6 @@ export class ChannelState<StreamChatGenerics extends ExtendableGenerics = Defaul
24
25
  watcher_count: number;
25
26
  typing: Record<string, Event<StreamChatGenerics>>;
26
27
  read: ChannelReadStatus<StreamChatGenerics>;
27
- messages: Array<ReturnType<ChannelState<StreamChatGenerics>['formatMessage']>>;
28
28
  pinnedMessages: Array<ReturnType<ChannelState<StreamChatGenerics>['formatMessage']>>;
29
29
  threads: Record<string, Array<ReturnType<ChannelState<StreamChatGenerics>['formatMessage']>>>;
30
30
  mutedUsers: Array<UserResponse<StreamChatGenerics>>;
@@ -40,12 +40,23 @@ export class ChannelState<StreamChatGenerics extends ExtendableGenerics = Defaul
40
40
  * be pushed on to message list.
41
41
  */
42
42
  isUpToDate: boolean;
43
+ /**
44
+ * Disjoint lists of messages
45
+ * Users can jump in the message list (with searching) and this can result in disjoint lists of messages
46
+ * The state manages these lists and merges them when lists overlap
47
+ * The messages array contains the currently active set
48
+ */
49
+ messageSets: {
50
+ isCurrent: boolean;
51
+ isLatest: boolean;
52
+ messages: Array<ReturnType<ChannelState<StreamChatGenerics>['formatMessage']>>;
53
+ }[] = [];
43
54
  constructor(channel: Channel<StreamChatGenerics>) {
44
55
  this._channel = channel;
45
56
  this.watcher_count = 0;
46
57
  this.typing = {};
47
58
  this.read = {};
48
- this.messages = [];
59
+ this.initMessages();
49
60
  this.pinnedMessages = [];
50
61
  this.threads = {};
51
62
  // a list of users to hide messages from
@@ -64,20 +75,49 @@ export class ChannelState<StreamChatGenerics extends ExtendableGenerics = Defaul
64
75
  this.last_message_at = channel?.state?.last_message_at != null ? new Date(channel.state.last_message_at) : null;
65
76
  }
66
77
 
78
+ get messages() {
79
+ return this.messageSets.find((s) => s.isCurrent)?.messages || [];
80
+ }
81
+
82
+ set messages(messages: Array<ReturnType<ChannelState<StreamChatGenerics>['formatMessage']>>) {
83
+ const index = this.messageSets.findIndex((s) => s.isCurrent);
84
+ this.messageSets[index].messages = messages;
85
+ }
86
+
87
+ /**
88
+ * The list of latest messages
89
+ * The messages array not always contains the latest messages (for example if a user searched for an earlier message, that is in a different message set)
90
+ */
91
+ get latestMessages() {
92
+ return this.messageSets.find((s) => s.isLatest)?.messages || [];
93
+ }
94
+
95
+ set latestMessages(messages: Array<ReturnType<ChannelState<StreamChatGenerics>['formatMessage']>>) {
96
+ const index = this.messageSets.findIndex((s) => s.isLatest);
97
+ this.messageSets[index].messages = messages;
98
+ }
99
+
67
100
  /**
68
101
  * addMessageSorted - Add a message to the state
69
102
  *
70
103
  * @param {MessageResponse<StreamChatGenerics>} newMessage A new message
71
104
  * @param {boolean} timestampChanged Whether updating a message with changed created_at value.
72
105
  * @param {boolean} addIfDoesNotExist Add message if it is not in the list, used to prevent out of order updated messages from being added.
73
- *
106
+ * @param {MessageSetType} messageSetToAddToIfDoesNotExist Which message set to add to if message is not in the list (only used if addIfDoesNotExist is true)
74
107
  */
75
108
  addMessageSorted(
76
109
  newMessage: MessageResponse<StreamChatGenerics>,
77
110
  timestampChanged = false,
78
111
  addIfDoesNotExist = true,
112
+ messageSetToAddToIfDoesNotExist: MessageSetType = 'latest',
79
113
  ) {
80
- return this.addMessagesSorted([newMessage], timestampChanged, false, addIfDoesNotExist);
114
+ return this.addMessagesSorted(
115
+ [newMessage],
116
+ timestampChanged,
117
+ false,
118
+ addIfDoesNotExist,
119
+ messageSetToAddToIfDoesNotExist,
120
+ );
81
121
  }
82
122
 
83
123
  /**
@@ -109,6 +149,7 @@ export class ChannelState<StreamChatGenerics extends ExtendableGenerics = Defaul
109
149
  * @param {boolean} timestampChanged Whether updating messages with changed created_at value.
110
150
  * @param {boolean} initializing Whether channel is being initialized.
111
151
  * @param {boolean} addIfDoesNotExist Add message if it is not in the list, used to prevent out of order updated messages from being added.
152
+ * @param {MessageSetType} messageSetToAddToIfDoesNotExist Which message set to add to if messages are not in the list (only used if addIfDoesNotExist is true)
112
153
  *
113
154
  */
114
155
  addMessagesSorted(
@@ -116,46 +157,59 @@ export class ChannelState<StreamChatGenerics extends ExtendableGenerics = Defaul
116
157
  timestampChanged = false,
117
158
  initializing = false,
118
159
  addIfDoesNotExist = true,
160
+ messageSetToAddToIfDoesNotExist: MessageSetType = 'current',
119
161
  ) {
120
- for (let i = 0; i < newMessages.length; i += 1) {
121
- const isFromShadowBannedUser = newMessages[i].shadowed;
162
+ const { messagesToAdd, targetMessageSetIndex } = this.findTargetMessageSet(
163
+ newMessages,
164
+ addIfDoesNotExist,
165
+ messageSetToAddToIfDoesNotExist,
166
+ );
167
+
168
+ for (let i = 0; i < messagesToAdd.length; i += 1) {
169
+ const isFromShadowBannedUser = messagesToAdd[i].shadowed;
122
170
  if (isFromShadowBannedUser) {
123
171
  continue;
124
172
  }
125
- const message = this.formatMessage(newMessages[i]);
126
-
127
- if (message.user && this._channel?.cid) {
128
- /**
129
- * Store the reference to user for this channel, so that when we have to
130
- * handle updates to user, we can use the reference map, to determine which
131
- * channels need to be updated with updated user object.
132
- */
133
- this._channel.getClient().state.updateUserReference(message.user, this._channel.cid);
134
- }
173
+ const isMerging = messagesToAdd[i].created_at instanceof Date;
174
+ let message: ReturnType<ChannelState<StreamChatGenerics>['formatMessage']>;
175
+ if (isMerging) {
176
+ message = messagesToAdd[i] as ReturnType<ChannelState<StreamChatGenerics>['formatMessage']>;
177
+ } else {
178
+ message = this.formatMessage(messagesToAdd[i] as MessageResponse<StreamChatGenerics>);
179
+
180
+ if (message.user && this._channel?.cid) {
181
+ /**
182
+ * Store the reference to user for this channel, so that when we have to
183
+ * handle updates to user, we can use the reference map, to determine which
184
+ * channels need to be updated with updated user object.
185
+ */
186
+ this._channel.getClient().state.updateUserReference(message.user, this._channel.cid);
187
+ }
135
188
 
136
- if (initializing && message.id && this.threads[message.id]) {
137
- // If we are initializing the state of channel (e.g., in case of connection recovery),
138
- // then in that case we remove thread related to this message from threads object.
139
- // This way we can ensure that we don't have any stale data in thread object
140
- // and consumer can refetch the replies.
141
- delete this.threads[message.id];
142
- }
189
+ if (initializing && message.id && this.threads[message.id]) {
190
+ // If we are initializing the state of channel (e.g., in case of connection recovery),
191
+ // then in that case we remove thread related to this message from threads object.
192
+ // This way we can ensure that we don't have any stale data in thread object
193
+ // and consumer can refetch the replies.
194
+ delete this.threads[message.id];
195
+ }
143
196
 
144
- if (!this.last_message_at) {
145
- this.last_message_at = new Date(message.created_at.getTime());
146
- }
197
+ if (!this.last_message_at) {
198
+ this.last_message_at = new Date(message.created_at.getTime());
199
+ }
147
200
 
148
- if (message.created_at.getTime() > this.last_message_at.getTime()) {
149
- this.last_message_at = new Date(message.created_at.getTime());
201
+ if (message.created_at.getTime() > this.last_message_at.getTime()) {
202
+ this.last_message_at = new Date(message.created_at.getTime());
203
+ }
150
204
  }
151
205
 
152
206
  // update or append the messages...
153
207
  const parentID = message.parent_id;
154
208
 
155
- // add to the main message list
156
- if (!parentID || message.show_in_channel) {
157
- this.messages = this._addToMessageList(
158
- this.messages,
209
+ // add to the given message set
210
+ if ((!parentID || message.show_in_channel) && targetMessageSetIndex !== -1) {
211
+ this.messageSets[targetMessageSetIndex].messages = this._addToMessageList(
212
+ this.messageSets[targetMessageSetIndex].messages,
159
213
  message,
160
214
  timestampChanged,
161
215
  'created_at',
@@ -172,7 +226,7 @@ export class ChannelState<StreamChatGenerics extends ExtendableGenerics = Defaul
172
226
  * message is "oldest" message, and newer messages are therefore not loaded.
173
227
  * This can also occur if an old thread message is updated.
174
228
  */
175
- if (parentID && !initializing) {
229
+ if (parentID && !initializing && !isMerging) {
176
230
  const thread = this.threads[parentID] || [];
177
231
  const threadMessages = this._addToMessageList(
178
232
  thread,
@@ -286,12 +340,14 @@ export class ChannelState<StreamChatGenerics extends ExtendableGenerics = Defaul
286
340
  updated_at: m.updated_at?.toString(),
287
341
  } as unknown) as MessageResponse<StreamChatGenerics>);
288
342
 
289
- const updatedMessages = this.messages
290
- .filter((msg) => msg.quoted_message_id === message.id)
291
- .map(parseMessage)
292
- .map((msg) => ({ ...msg, quoted_message: { ...message, attachments: [] } }));
343
+ this.messageSets.forEach((set) => {
344
+ const updatedMessages = set.messages
345
+ .filter((msg) => msg.quoted_message_id === message.id)
346
+ .map(parseMessage)
347
+ .map((msg) => ({ ...msg, quoted_message: { ...message, attachments: [] } }));
293
348
 
294
- this.addMessagesSorted(updatedMessages, true);
349
+ this.addMessagesSorted(updatedMessages, true);
350
+ });
295
351
  }
296
352
 
297
353
  /**
@@ -322,9 +378,14 @@ export class ChannelState<StreamChatGenerics extends ExtendableGenerics = Defaul
322
378
  }
323
379
 
324
380
  if ((!show_in_channel && !parent_id) || show_in_channel) {
325
- const msgIndex = this.messages.findIndex((msg) => msg.id === message.id);
326
- if (msgIndex !== -1) {
327
- this.messages[msgIndex] = updateFunc(this.messages[msgIndex]);
381
+ const messageSetIndex = this.findMessageSetIndex(message);
382
+ if (messageSetIndex !== -1) {
383
+ const msgIndex = this.messageSets[messageSetIndex].messages.findIndex((msg) => msg.id === message.id);
384
+ if (msgIndex !== -1) {
385
+ this.messageSets[messageSetIndex].messages[msgIndex] = updateFunc(
386
+ this.messageSets[messageSetIndex].messages[msgIndex],
387
+ );
388
+ }
328
389
  }
329
390
  }
330
391
 
@@ -442,9 +503,15 @@ export class ChannelState<StreamChatGenerics extends ExtendableGenerics = Defaul
442
503
  this.threads[messageToRemove.parent_id] = threadMessages;
443
504
  isRemoved = removed;
444
505
  } else {
445
- const { removed, result: messages } = this.removeMessageFromArray(this.messages, messageToRemove);
446
- this.messages = messages;
447
- isRemoved = removed;
506
+ const messageSetIndex = this.findMessageSetIndex(messageToRemove);
507
+ if (messageSetIndex !== -1) {
508
+ const { removed, result: messages } = this.removeMessageFromArray(
509
+ this.messageSets[messageSetIndex].messages,
510
+ messageToRemove,
511
+ );
512
+ this.messageSets[messageSetIndex].messages = messages;
513
+ isRemoved = removed;
514
+ }
448
515
  }
449
516
 
450
517
  return isRemoved;
@@ -477,7 +544,7 @@ export class ChannelState<StreamChatGenerics extends ExtendableGenerics = Defaul
477
544
  }
478
545
  };
479
546
 
480
- _updateUserMessages(this.messages, user);
547
+ this.messageSets.forEach((set) => _updateUserMessages(set.messages, user));
481
548
 
482
549
  for (const parentId in this.threads) {
483
550
  _updateUserMessages(this.threads[parentId], user);
@@ -535,7 +602,7 @@ export class ChannelState<StreamChatGenerics extends ExtendableGenerics = Defaul
535
602
  }
536
603
  };
537
604
 
538
- _deleteUserMessages(this.messages, user, hardDelete);
605
+ this.messageSets.forEach((set) => _deleteUserMessages(set.messages, user, hardDelete));
539
606
 
540
607
  for (const parentId in this.threads) {
541
608
  _deleteUserMessages(this.threads[parentId], user, hardDelete);
@@ -549,9 +616,9 @@ export class ChannelState<StreamChatGenerics extends ExtendableGenerics = Defaul
549
616
  *
550
617
  */
551
618
  filterErrorMessages() {
552
- const filteredMessages = this.messages.filter((message) => message.type !== 'error');
619
+ const filteredMessages = this.latestMessages.filter((message) => message.type !== 'error');
553
620
 
554
- this.messages = filteredMessages;
621
+ this.latestMessages = filteredMessages;
555
622
  }
556
623
 
557
624
  /**
@@ -577,7 +644,129 @@ export class ChannelState<StreamChatGenerics extends ExtendableGenerics = Defaul
577
644
  }
578
645
 
579
646
  clearMessages() {
580
- this.messages = [];
647
+ this.initMessages();
581
648
  this.pinnedMessages = [];
582
649
  }
650
+
651
+ initMessages() {
652
+ this.messageSets = [{ messages: [], isLatest: true, isCurrent: true }];
653
+ }
654
+
655
+ /**
656
+ * loadMessageIntoState - Loads a given message (and messages around it) into the state
657
+ *
658
+ * @param {string} messageId The id of the message, or 'latest' to indicate switching to the latest messages
659
+ * @param {string} parentMessageId The id of the parent message, if we want load a thread reply
660
+ */
661
+ async loadMessageIntoState(messageId: string | 'latest', parentMessageId?: string) {
662
+ let messageSetIndex: number;
663
+ let switchedToMessageSet = false;
664
+ let loadedMessageThread = false;
665
+ const messageIdToFind = parentMessageId || messageId;
666
+ if (messageId === 'latest') {
667
+ if (this.messages === this.latestMessages) {
668
+ return;
669
+ }
670
+ messageSetIndex = this.messageSets.findIndex((s) => s.isLatest);
671
+ } else {
672
+ messageSetIndex = this.findMessageSetIndex({ id: messageIdToFind });
673
+ }
674
+ if (messageSetIndex !== -1) {
675
+ this.switchToMessageSet(messageSetIndex);
676
+ switchedToMessageSet = true;
677
+ }
678
+ loadedMessageThread = !parentMessageId || !!this.threads[parentMessageId]?.find((m) => m.id === messageId);
679
+ if (switchedToMessageSet && loadedMessageThread) {
680
+ return;
681
+ }
682
+ if (!switchedToMessageSet) {
683
+ await this._channel.query({ messages: { id_around: messageIdToFind, limit: 25 } }, 'new');
684
+ }
685
+ if (!loadedMessageThread && parentMessageId) {
686
+ await this._channel.getReplies(parentMessageId, { id_around: messageId, limit: 25 });
687
+ }
688
+ messageSetIndex = this.findMessageSetIndex({ id: messageIdToFind });
689
+ if (messageSetIndex !== -1) {
690
+ this.switchToMessageSet(messageSetIndex);
691
+ }
692
+ }
693
+
694
+ private switchToMessageSet(index: number) {
695
+ const currentMessages = this.messageSets.find((s) => s.isCurrent);
696
+ if (!currentMessages) {
697
+ return;
698
+ }
699
+ currentMessages.isCurrent = false;
700
+ this.messageSets[index].isCurrent = true;
701
+ }
702
+
703
+ private areMessageSetsOverlap(messages1: Array<{ id: string }>, messages2: Array<{ id: string }>) {
704
+ return messages1.some((m1) => messages2.find((m2) => m1.id === m2.id));
705
+ }
706
+
707
+ private findMessageSetIndex(message: { id?: string }) {
708
+ return this.messageSets.findIndex((set) => !!set.messages.find((m) => m.id === message.id));
709
+ }
710
+
711
+ private findTargetMessageSet(
712
+ newMessages: MessageResponse<StreamChatGenerics>[],
713
+ addIfDoesNotExist = true,
714
+ messageSetToAddToIfDoesNotExist: MessageSetType = 'current',
715
+ ) {
716
+ let messagesToAdd: (
717
+ | MessageResponse<StreamChatGenerics>
718
+ | ReturnType<ChannelState<StreamChatGenerics>['formatMessage']>
719
+ )[] = newMessages;
720
+ let targetMessageSetIndex!: number;
721
+ if (addIfDoesNotExist) {
722
+ const overlappingMessageSetIndices = this.messageSets
723
+ .map((_, i) => i)
724
+ .filter((i) => this.areMessageSetsOverlap(this.messageSets[i].messages, newMessages));
725
+ switch (messageSetToAddToIfDoesNotExist) {
726
+ case 'new':
727
+ if (overlappingMessageSetIndices.length > 0) {
728
+ targetMessageSetIndex = overlappingMessageSetIndices[0];
729
+ // No new message set is created if newMessages only contains thread replies
730
+ } else if (newMessages.some((m) => !m.parent_id)) {
731
+ this.messageSets.push({ messages: [], isCurrent: false, isLatest: false });
732
+ targetMessageSetIndex = this.messageSets.length - 1;
733
+ }
734
+ break;
735
+ case 'current':
736
+ targetMessageSetIndex = this.messageSets.findIndex((s) => s.isCurrent);
737
+ break;
738
+ case 'latest':
739
+ targetMessageSetIndex = this.messageSets.findIndex((s) => s.isLatest);
740
+ break;
741
+ default:
742
+ targetMessageSetIndex = -1;
743
+ }
744
+ // when merging the target set will be the first one from the overlapping message sets
745
+ const mergeTargetMessageSetIndex = overlappingMessageSetIndices.splice(0, 1)[0];
746
+ const mergeSourceMessageSetIndices = [...overlappingMessageSetIndices];
747
+ if (mergeTargetMessageSetIndex !== undefined && mergeTargetMessageSetIndex !== targetMessageSetIndex) {
748
+ mergeSourceMessageSetIndices.push(targetMessageSetIndex);
749
+ }
750
+ // merge message sets
751
+ if (mergeSourceMessageSetIndices.length > 0) {
752
+ const target = this.messageSets[mergeTargetMessageSetIndex];
753
+ const sources = this.messageSets.filter((_, i) => mergeSourceMessageSetIndices.indexOf(i) !== -1);
754
+ sources.forEach((messageSet) => {
755
+ target.isLatest = target.isLatest || messageSet.isLatest;
756
+ target.isCurrent = target.isCurrent || messageSet.isCurrent;
757
+ messagesToAdd = [...messagesToAdd, ...messageSet.messages];
758
+ });
759
+ sources.forEach((s) => this.messageSets.splice(this.messageSets.indexOf(s), 1));
760
+ const overlappingMessageSetIndex = this.messageSets.findIndex((s) =>
761
+ this.areMessageSetsOverlap(s.messages, newMessages),
762
+ );
763
+ targetMessageSetIndex = overlappingMessageSetIndex;
764
+ }
765
+ } else {
766
+ // assumes that all new messages belong to the same set
767
+ targetMessageSetIndex = this.findMessageSetIndex(newMessages[0]);
768
+ }
769
+
770
+ return { targetMessageSetIndex, messagesToAdd };
771
+ }
583
772
  }
package/src/client.ts CHANGED
@@ -86,6 +86,10 @@ import {
86
86
  PermissionAPIResponse,
87
87
  PermissionsAPIResponse,
88
88
  PushProvider,
89
+ PushProviderID,
90
+ PushProviderConfig,
91
+ PushProviderUpsertResponse,
92
+ PushProviderListResponse,
89
93
  ReactionResponse,
90
94
  SearchOptions,
91
95
  SearchPayload,
@@ -1473,10 +1477,10 @@ export class StreamChat<StreamChatGenerics extends ExtendableGenerics = DefaultG
1473
1477
  c.initialized = true;
1474
1478
 
1475
1479
  if (skipInitialization === undefined) {
1476
- c._initializeState(channelState);
1480
+ c._initializeState(channelState, 'latest');
1477
1481
  } else if (!skipInitialization.includes(channelState.channel.id)) {
1478
1482
  c.state.clearMessages();
1479
- c._initializeState(channelState);
1483
+ c._initializeState(channelState, 'latest');
1480
1484
  }
1481
1485
 
1482
1486
  channels.push(c);
@@ -2900,4 +2904,43 @@ export class StreamChat<StreamChatGenerics extends ExtendableGenerics = DefaultG
2900
2904
  async _listImports(options: ListImportsPaginationOptions) {
2901
2905
  return await this.get<APIResponse & ListImportsResponse>(this.baseURL + `/imports`, options);
2902
2906
  }
2907
+
2908
+ /**
2909
+ * upsertPushProvider - Create or Update a push provider
2910
+ *
2911
+ * Note: Works only for v2 push version is enabled on app settings.
2912
+ *
2913
+ * @param {PushProviderConfig} configuration of the provider you want to create or update
2914
+ *
2915
+ * @return {APIResponse & PushProviderUpsertResponse} A push provider
2916
+ */
2917
+ async upsertPushProvider(pushProvider: PushProviderConfig) {
2918
+ return await this.post<APIResponse & PushProviderUpsertResponse>(this.baseURL + `/push_providers`, {
2919
+ push_provider: pushProvider,
2920
+ });
2921
+ }
2922
+
2923
+ /**
2924
+ * deletePushProvider - Delete a push provider
2925
+ *
2926
+ * Note: Works only for v2 push version is enabled on app settings.
2927
+ *
2928
+ * @param {PushProviderID} type and foreign id of the push provider to be deleted
2929
+ *
2930
+ * @return {APIResponse} An API response
2931
+ */
2932
+ async deletePushProvider({ type, name }: PushProviderID) {
2933
+ return await this.delete<APIResponse>(this.baseURL + `/push_providers/${type}/${name}`);
2934
+ }
2935
+
2936
+ /**
2937
+ * listPushProviders - Get all push providers in the app
2938
+ *
2939
+ * Note: Works only for v2 push version is enabled on app settings.
2940
+ *
2941
+ * @return {APIResponse & PushProviderListResponse} A push provider
2942
+ */
2943
+ async listPushProviders() {
2944
+ return await this.get<APIResponse & PushProviderListResponse>(this.baseURL + `/push_providers`);
2945
+ }
2903
2946
  }
package/src/types.ts CHANGED
@@ -120,6 +120,7 @@ export type AppSettingsAPIResponse<StreamChatGenerics extends ExtendableGenerics
120
120
  apn?: APNConfig;
121
121
  firebase?: FirebaseConfig;
122
122
  huawei?: HuaweiConfig;
123
+ providers?: PushProviderConfig[];
123
124
  xiaomi?: XiaomiConfig;
124
125
  };
125
126
  revoke_tokens_issued_before?: string | null;
@@ -1610,6 +1611,54 @@ export type CheckPushInput<StreamChatGenerics extends ExtendableGenerics = Defau
1610
1611
 
1611
1612
  export type PushProvider = 'apn' | 'firebase' | 'huawei' | 'xiaomi';
1612
1613
 
1614
+ export type PushProviderConfig = PushProviderCommon &
1615
+ PushProviderAPN &
1616
+ PushProviderFirebase &
1617
+ PushProviderHuawei &
1618
+ PushProviderXiaomi;
1619
+
1620
+ export type PushProviderID = {
1621
+ name: string;
1622
+ type: PushProvider;
1623
+ };
1624
+
1625
+ export type PushProviderCommon = {
1626
+ created_at: string;
1627
+ updated_at: string;
1628
+ description?: string;
1629
+ disabled_at?: string;
1630
+ disabled_reason?: string;
1631
+ };
1632
+
1633
+ export type PushProviderAPN = {
1634
+ apn_auth_key?: string;
1635
+ apn_auth_type?: 'token' | 'certificate';
1636
+ apn_development?: boolean;
1637
+ apn_host?: string;
1638
+ apn_key_id?: string;
1639
+ apn_notification_template?: string;
1640
+ apn_p12_cert?: string;
1641
+ apn_team_id?: string;
1642
+ apn_topic?: string;
1643
+ };
1644
+
1645
+ export type PushProviderFirebase = {
1646
+ firebase_credentials?: string;
1647
+ firebase_data_template?: string;
1648
+ firebase_notification_template?: string;
1649
+ firebase_server_key?: string;
1650
+ };
1651
+
1652
+ export type PushProviderHuawei = {
1653
+ huawei_app_id?: string;
1654
+ huawei_app_secret?: string;
1655
+ };
1656
+
1657
+ export type PushProviderXiaomi = {
1658
+ xiaomi_package_name?: string;
1659
+ xiaomi_secret?: string;
1660
+ };
1661
+
1613
1662
  export type CommandVariants<StreamChatGenerics extends ExtendableGenerics = DefaultGenerics> =
1614
1663
  | 'all'
1615
1664
  | 'ban'
@@ -2195,3 +2244,13 @@ export type ImportTask = {
2195
2244
  result?: UR;
2196
2245
  size?: number;
2197
2246
  };
2247
+
2248
+ export type MessageSetType = 'latest' | 'current' | 'new';
2249
+
2250
+ export type PushProviderUpsertResponse = {
2251
+ push_provider: PushProvider;
2252
+ };
2253
+
2254
+ export type PushProviderListResponse = {
2255
+ push_providers: PushProvider[];
2256
+ };