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.
package/dist/index.js CHANGED
@@ -126,6 +126,13 @@ var ChannelState = /*#__PURE__*/function () {
126
126
  * When false, any new message (received by websocket event - message.new) will not
127
127
  * be pushed on to message list.
128
128
  */
129
+
130
+ /**
131
+ * Disjoint lists of messages
132
+ * Users can jump in the message list (with searching) and this can result in disjoint lists of messages
133
+ * The state manages these lists and merges them when lists overlap
134
+ * The messages array contains the currently active set
135
+ */
129
136
  function ChannelState(channel) {
130
137
  var _this = this,
131
138
  _channel$state;
@@ -140,8 +147,6 @@ var ChannelState = /*#__PURE__*/function () {
140
147
 
141
148
  _defineProperty__default['default'](this, "read", void 0);
142
149
 
143
- _defineProperty__default['default'](this, "messages", void 0);
144
-
145
150
  _defineProperty__default['default'](this, "pinnedMessages", void 0);
146
151
 
147
152
  _defineProperty__default['default'](this, "threads", void 0);
@@ -160,6 +165,8 @@ var ChannelState = /*#__PURE__*/function () {
160
165
 
161
166
  _defineProperty__default['default'](this, "isUpToDate", void 0);
162
167
 
168
+ _defineProperty__default['default'](this, "messageSets", []);
169
+
163
170
  _defineProperty__default['default'](this, "setIsUpToDate", function (isUpToDate) {
164
171
  _this.isUpToDate = isUpToDate;
165
172
  });
@@ -189,7 +196,9 @@ var ChannelState = /*#__PURE__*/function () {
189
196
  }
190
197
  };
191
198
 
192
- _updateUserMessages(_this.messages, user);
199
+ _this.messageSets.forEach(function (set) {
200
+ return _updateUserMessages(set.messages, user);
201
+ });
193
202
 
194
203
  for (var parentId in _this.threads) {
195
204
  _updateUserMessages(_this.threads[parentId], user);
@@ -243,7 +252,9 @@ var ChannelState = /*#__PURE__*/function () {
243
252
  }
244
253
  };
245
254
 
246
- _deleteUserMessages(_this.messages, user, hardDelete);
255
+ _this.messageSets.forEach(function (set) {
256
+ return _deleteUserMessages(set.messages, user, hardDelete);
257
+ });
247
258
 
248
259
  for (var parentId in _this.threads) {
249
260
  _deleteUserMessages(_this.threads[parentId], user, hardDelete);
@@ -256,7 +267,7 @@ var ChannelState = /*#__PURE__*/function () {
256
267
  this.watcher_count = 0;
257
268
  this.typing = {};
258
269
  this.read = {};
259
- this.messages = [];
270
+ this.initMessages();
260
271
  this.pinnedMessages = [];
261
272
  this.threads = {}; // a list of users to hide messages from
262
273
 
@@ -275,22 +286,58 @@ var ChannelState = /*#__PURE__*/function () {
275
286
  this.isUpToDate = true;
276
287
  this.last_message_at = (channel === null || channel === void 0 ? void 0 : (_channel$state = channel.state) === null || _channel$state === void 0 ? void 0 : _channel$state.last_message_at) != null ? new Date(channel.state.last_message_at) : null;
277
288
  }
278
- /**
279
- * addMessageSorted - Add a message to the state
280
- *
281
- * @param {MessageResponse<StreamChatGenerics>} newMessage A new message
282
- * @param {boolean} timestampChanged Whether updating a message with changed created_at value.
283
- * @param {boolean} addIfDoesNotExist Add message if it is not in the list, used to prevent out of order updated messages from being added.
284
- *
285
- */
286
-
287
289
 
288
290
  _createClass__default['default'](ChannelState, [{
291
+ key: "messages",
292
+ get: function get() {
293
+ var _this$messageSets$fin;
294
+
295
+ return ((_this$messageSets$fin = this.messageSets.find(function (s) {
296
+ return s.isCurrent;
297
+ })) === null || _this$messageSets$fin === void 0 ? void 0 : _this$messageSets$fin.messages) || [];
298
+ },
299
+ set: function set(messages) {
300
+ var index = this.messageSets.findIndex(function (s) {
301
+ return s.isCurrent;
302
+ });
303
+ this.messageSets[index].messages = messages;
304
+ }
305
+ /**
306
+ * The list of latest messages
307
+ * 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)
308
+ */
309
+
310
+ }, {
311
+ key: "latestMessages",
312
+ get: function get() {
313
+ var _this$messageSets$fin2;
314
+
315
+ return ((_this$messageSets$fin2 = this.messageSets.find(function (s) {
316
+ return s.isLatest;
317
+ })) === null || _this$messageSets$fin2 === void 0 ? void 0 : _this$messageSets$fin2.messages) || [];
318
+ },
319
+ set: function set(messages) {
320
+ var index = this.messageSets.findIndex(function (s) {
321
+ return s.isLatest;
322
+ });
323
+ this.messageSets[index].messages = messages;
324
+ }
325
+ /**
326
+ * addMessageSorted - Add a message to the state
327
+ *
328
+ * @param {MessageResponse<StreamChatGenerics>} newMessage A new message
329
+ * @param {boolean} timestampChanged Whether updating a message with changed created_at value.
330
+ * @param {boolean} addIfDoesNotExist Add message if it is not in the list, used to prevent out of order updated messages from being added.
331
+ * @param {MessageSetType} messageSetToAddToIfDoesNotExist Which message set to add to if message is not in the list (only used if addIfDoesNotExist is true)
332
+ */
333
+
334
+ }, {
289
335
  key: "addMessageSorted",
290
336
  value: function addMessageSorted(newMessage) {
291
337
  var timestampChanged = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
292
338
  var addIfDoesNotExist = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true;
293
- return this.addMessagesSorted([newMessage], timestampChanged, false, addIfDoesNotExist);
339
+ var messageSetToAddToIfDoesNotExist = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 'latest';
340
+ return this.addMessagesSorted([newMessage], timestampChanged, false, addIfDoesNotExist, messageSetToAddToIfDoesNotExist);
294
341
  }
295
342
  /**
296
343
  * formatMessage - Takes the message object. Parses the dates, sets __html
@@ -322,6 +369,7 @@ var ChannelState = /*#__PURE__*/function () {
322
369
  * @param {boolean} timestampChanged Whether updating messages with changed created_at value.
323
370
  * @param {boolean} initializing Whether channel is being initialized.
324
371
  * @param {boolean} addIfDoesNotExist Add message if it is not in the list, used to prevent out of order updated messages from being added.
372
+ * @param {MessageSetType} messageSetToAddToIfDoesNotExist Which message set to add to if messages are not in the list (only used if addIfDoesNotExist is true)
325
373
  *
326
374
  */
327
375
 
@@ -331,48 +379,60 @@ var ChannelState = /*#__PURE__*/function () {
331
379
  var timestampChanged = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
332
380
  var initializing = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
333
381
  var addIfDoesNotExist = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : true;
382
+ var messageSetToAddToIfDoesNotExist = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 'current';
334
383
 
335
- for (var i = 0; i < newMessages.length; i += 1) {
336
- var _this$_channel;
384
+ var _this$findTargetMessa = this.findTargetMessageSet(newMessages, addIfDoesNotExist, messageSetToAddToIfDoesNotExist),
385
+ messagesToAdd = _this$findTargetMessa.messagesToAdd,
386
+ targetMessageSetIndex = _this$findTargetMessa.targetMessageSetIndex;
337
387
 
338
- var isFromShadowBannedUser = newMessages[i].shadowed;
388
+ for (var i = 0; i < messagesToAdd.length; i += 1) {
389
+ var isFromShadowBannedUser = messagesToAdd[i].shadowed;
339
390
 
340
391
  if (isFromShadowBannedUser) {
341
392
  continue;
342
393
  }
343
394
 
344
- var message = this.formatMessage(newMessages[i]);
395
+ var isMerging = messagesToAdd[i].created_at instanceof Date;
396
+ var message = void 0;
345
397
 
346
- if (message.user && (_this$_channel = this._channel) !== null && _this$_channel !== void 0 && _this$_channel.cid) {
347
- /**
348
- * Store the reference to user for this channel, so that when we have to
349
- * handle updates to user, we can use the reference map, to determine which
350
- * channels need to be updated with updated user object.
351
- */
352
- this._channel.getClient().state.updateUserReference(message.user, this._channel.cid);
353
- }
398
+ if (isMerging) {
399
+ message = messagesToAdd[i];
400
+ } else {
401
+ var _this$_channel;
354
402
 
355
- if (initializing && message.id && this.threads[message.id]) {
356
- // If we are initializing the state of channel (e.g., in case of connection recovery),
357
- // then in that case we remove thread related to this message from threads object.
358
- // This way we can ensure that we don't have any stale data in thread object
359
- // and consumer can refetch the replies.
360
- delete this.threads[message.id];
361
- }
403
+ message = this.formatMessage(messagesToAdd[i]);
362
404
 
363
- if (!this.last_message_at) {
364
- this.last_message_at = new Date(message.created_at.getTime());
365
- }
405
+ if (message.user && (_this$_channel = this._channel) !== null && _this$_channel !== void 0 && _this$_channel.cid) {
406
+ /**
407
+ * Store the reference to user for this channel, so that when we have to
408
+ * handle updates to user, we can use the reference map, to determine which
409
+ * channels need to be updated with updated user object.
410
+ */
411
+ this._channel.getClient().state.updateUserReference(message.user, this._channel.cid);
412
+ }
413
+
414
+ if (initializing && message.id && this.threads[message.id]) {
415
+ // If we are initializing the state of channel (e.g., in case of connection recovery),
416
+ // then in that case we remove thread related to this message from threads object.
417
+ // This way we can ensure that we don't have any stale data in thread object
418
+ // and consumer can refetch the replies.
419
+ delete this.threads[message.id];
420
+ }
366
421
 
367
- if (message.created_at.getTime() > this.last_message_at.getTime()) {
368
- this.last_message_at = new Date(message.created_at.getTime());
422
+ if (!this.last_message_at) {
423
+ this.last_message_at = new Date(message.created_at.getTime());
424
+ }
425
+
426
+ if (message.created_at.getTime() > this.last_message_at.getTime()) {
427
+ this.last_message_at = new Date(message.created_at.getTime());
428
+ }
369
429
  } // update or append the messages...
370
430
 
371
431
 
372
- var parentID = message.parent_id; // add to the main message list
432
+ var parentID = message.parent_id; // add to the given message set
373
433
 
374
- if (!parentID || message.show_in_channel) {
375
- this.messages = this._addToMessageList(this.messages, message, timestampChanged, 'created_at', addIfDoesNotExist);
434
+ if ((!parentID || message.show_in_channel) && targetMessageSetIndex !== -1) {
435
+ this.messageSets[targetMessageSetIndex].messages = this._addToMessageList(this.messageSets[targetMessageSetIndex].messages, message, timestampChanged, 'created_at', addIfDoesNotExist);
376
436
  }
377
437
  /**
378
438
  * Add message to thread if applicable and the message
@@ -385,7 +445,7 @@ var ChannelState = /*#__PURE__*/function () {
385
445
  */
386
446
 
387
447
 
388
- if (parentID && !initializing) {
448
+ if (parentID && !initializing && !isMerging) {
389
449
  var thread = this.threads[parentID] || [];
390
450
 
391
451
  var threadMessages = this._addToMessageList(thread, message, timestampChanged, 'created_at', addIfDoesNotExist);
@@ -496,6 +556,8 @@ var ChannelState = /*#__PURE__*/function () {
496
556
  }, {
497
557
  key: "removeQuotedMessageReferences",
498
558
  value: function removeQuotedMessageReferences(message) {
559
+ var _this4 = this;
560
+
499
561
  var parseMessage = function parseMessage(m) {
500
562
  var _m$pinned_at, _m$updated_at;
501
563
 
@@ -506,16 +568,19 @@ var ChannelState = /*#__PURE__*/function () {
506
568
  });
507
569
  };
508
570
 
509
- var updatedMessages = this.messages.filter(function (msg) {
510
- return msg.quoted_message_id === message.id;
511
- }).map(parseMessage).map(function (msg) {
512
- return _objectSpread$7(_objectSpread$7({}, msg), {}, {
513
- quoted_message: _objectSpread$7(_objectSpread$7({}, message), {}, {
514
- attachments: []
515
- })
571
+ this.messageSets.forEach(function (set) {
572
+ var updatedMessages = set.messages.filter(function (msg) {
573
+ return msg.quoted_message_id === message.id;
574
+ }).map(parseMessage).map(function (msg) {
575
+ return _objectSpread$7(_objectSpread$7({}, msg), {}, {
576
+ quoted_message: _objectSpread$7(_objectSpread$7({}, message), {}, {
577
+ attachments: []
578
+ })
579
+ });
516
580
  });
581
+
582
+ _this4.addMessagesSorted(updatedMessages, true);
517
583
  });
518
- this.addMessagesSorted(updatedMessages, true);
519
584
  }
520
585
  /**
521
586
  * Updates all instances of given message in channel state
@@ -543,12 +608,16 @@ var ChannelState = /*#__PURE__*/function () {
543
608
  }
544
609
 
545
610
  if (!show_in_channel && !parent_id || show_in_channel) {
546
- var _msgIndex = this.messages.findIndex(function (msg) {
547
- return msg.id === message.id;
548
- });
611
+ var messageSetIndex = this.findMessageSetIndex(message);
612
+
613
+ if (messageSetIndex !== -1) {
614
+ var _msgIndex = this.messageSets[messageSetIndex].messages.findIndex(function (msg) {
615
+ return msg.id === message.id;
616
+ });
549
617
 
550
- if (_msgIndex !== -1) {
551
- this.messages[_msgIndex] = updateFunc(this.messages[_msgIndex]);
618
+ if (_msgIndex !== -1) {
619
+ this.messageSets[messageSetIndex].messages[_msgIndex] = updateFunc(this.messageSets[messageSetIndex].messages[_msgIndex]);
620
+ }
552
621
  }
553
622
  }
554
623
 
@@ -667,12 +736,16 @@ var ChannelState = /*#__PURE__*/function () {
667
736
  this.threads[messageToRemove.parent_id] = threadMessages;
668
737
  isRemoved = removed;
669
738
  } else {
670
- var _this$removeMessageFr3 = this.removeMessageFromArray(this.messages, messageToRemove),
671
- _removed = _this$removeMessageFr3.removed,
672
- messages = _this$removeMessageFr3.result;
739
+ var messageSetIndex = this.findMessageSetIndex(messageToRemove);
673
740
 
674
- this.messages = messages;
675
- isRemoved = _removed;
741
+ if (messageSetIndex !== -1) {
742
+ var _this$removeMessageFr3 = this.removeMessageFromArray(this.messageSets[messageSetIndex].messages, messageToRemove),
743
+ _removed = _this$removeMessageFr3.removed,
744
+ messages = _this$removeMessageFr3.result;
745
+
746
+ this.messageSets[messageSetIndex].messages = messages;
747
+ isRemoved = _removed;
748
+ }
676
749
  }
677
750
 
678
751
  return isRemoved;
@@ -685,10 +758,10 @@ var ChannelState = /*#__PURE__*/function () {
685
758
  *
686
759
  */
687
760
  function filterErrorMessages() {
688
- var filteredMessages = this.messages.filter(function (message) {
761
+ var filteredMessages = this.latestMessages.filter(function (message) {
689
762
  return message.type !== 'error';
690
763
  });
691
- this.messages = filteredMessages;
764
+ this.latestMessages = filteredMessages;
692
765
  }
693
766
  /**
694
767
  * clean - Remove stale data such as users that stayed in typing state for more than 5 seconds
@@ -722,9 +795,250 @@ var ChannelState = /*#__PURE__*/function () {
722
795
  }, {
723
796
  key: "clearMessages",
724
797
  value: function clearMessages() {
725
- this.messages = [];
798
+ this.initMessages();
726
799
  this.pinnedMessages = [];
727
800
  }
801
+ }, {
802
+ key: "initMessages",
803
+ value: function initMessages() {
804
+ this.messageSets = [{
805
+ messages: [],
806
+ isLatest: true,
807
+ isCurrent: true
808
+ }];
809
+ }
810
+ /**
811
+ * loadMessageIntoState - Loads a given message (and messages around it) into the state
812
+ *
813
+ * @param {string} messageId The id of the message, or 'latest' to indicate switching to the latest messages
814
+ * @param {string} parentMessageId The id of the parent message, if we want load a thread reply
815
+ */
816
+
817
+ }, {
818
+ key: "loadMessageIntoState",
819
+ value: function () {
820
+ var _loadMessageIntoState = _asyncToGenerator__default['default']( /*#__PURE__*/_regeneratorRuntime__default['default'].mark(function _callee(messageId, parentMessageId) {
821
+ var _this$threads$parentM;
822
+
823
+ var messageSetIndex, switchedToMessageSet, loadedMessageThread, messageIdToFind;
824
+ return _regeneratorRuntime__default['default'].wrap(function _callee$(_context) {
825
+ while (1) {
826
+ switch (_context.prev = _context.next) {
827
+ case 0:
828
+ switchedToMessageSet = false;
829
+ loadedMessageThread = false;
830
+ messageIdToFind = parentMessageId || messageId;
831
+
832
+ if (!(messageId === 'latest')) {
833
+ _context.next = 9;
834
+ break;
835
+ }
836
+
837
+ if (!(this.messages === this.latestMessages)) {
838
+ _context.next = 6;
839
+ break;
840
+ }
841
+
842
+ return _context.abrupt("return");
843
+
844
+ case 6:
845
+ messageSetIndex = this.messageSets.findIndex(function (s) {
846
+ return s.isLatest;
847
+ });
848
+ _context.next = 10;
849
+ break;
850
+
851
+ case 9:
852
+ messageSetIndex = this.findMessageSetIndex({
853
+ id: messageIdToFind
854
+ });
855
+
856
+ case 10:
857
+ if (messageSetIndex !== -1) {
858
+ this.switchToMessageSet(messageSetIndex);
859
+ switchedToMessageSet = true;
860
+ }
861
+
862
+ loadedMessageThread = !parentMessageId || !!((_this$threads$parentM = this.threads[parentMessageId]) !== null && _this$threads$parentM !== void 0 && _this$threads$parentM.find(function (m) {
863
+ return m.id === messageId;
864
+ }));
865
+
866
+ if (!(switchedToMessageSet && loadedMessageThread)) {
867
+ _context.next = 14;
868
+ break;
869
+ }
870
+
871
+ return _context.abrupt("return");
872
+
873
+ case 14:
874
+ if (switchedToMessageSet) {
875
+ _context.next = 17;
876
+ break;
877
+ }
878
+
879
+ _context.next = 17;
880
+ return this._channel.query({
881
+ messages: {
882
+ id_around: messageIdToFind,
883
+ limit: 25
884
+ }
885
+ }, 'new');
886
+
887
+ case 17:
888
+ if (!(!loadedMessageThread && parentMessageId)) {
889
+ _context.next = 20;
890
+ break;
891
+ }
892
+
893
+ _context.next = 20;
894
+ return this._channel.getReplies(parentMessageId, {
895
+ id_around: messageId,
896
+ limit: 25
897
+ });
898
+
899
+ case 20:
900
+ messageSetIndex = this.findMessageSetIndex({
901
+ id: messageIdToFind
902
+ });
903
+
904
+ if (messageSetIndex !== -1) {
905
+ this.switchToMessageSet(messageSetIndex);
906
+ }
907
+
908
+ case 22:
909
+ case "end":
910
+ return _context.stop();
911
+ }
912
+ }
913
+ }, _callee, this);
914
+ }));
915
+
916
+ function loadMessageIntoState(_x, _x2) {
917
+ return _loadMessageIntoState.apply(this, arguments);
918
+ }
919
+
920
+ return loadMessageIntoState;
921
+ }()
922
+ }, {
923
+ key: "switchToMessageSet",
924
+ value: function switchToMessageSet(index) {
925
+ var currentMessages = this.messageSets.find(function (s) {
926
+ return s.isCurrent;
927
+ });
928
+
929
+ if (!currentMessages) {
930
+ return;
931
+ }
932
+
933
+ currentMessages.isCurrent = false;
934
+ this.messageSets[index].isCurrent = true;
935
+ }
936
+ }, {
937
+ key: "areMessageSetsOverlap",
938
+ value: function areMessageSetsOverlap(messages1, messages2) {
939
+ return messages1.some(function (m1) {
940
+ return messages2.find(function (m2) {
941
+ return m1.id === m2.id;
942
+ });
943
+ });
944
+ }
945
+ }, {
946
+ key: "findMessageSetIndex",
947
+ value: function findMessageSetIndex(message) {
948
+ return this.messageSets.findIndex(function (set) {
949
+ return !!set.messages.find(function (m) {
950
+ return m.id === message.id;
951
+ });
952
+ });
953
+ }
954
+ }, {
955
+ key: "findTargetMessageSet",
956
+ value: function findTargetMessageSet(newMessages) {
957
+ var _this5 = this;
958
+
959
+ var addIfDoesNotExist = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
960
+ var messageSetToAddToIfDoesNotExist = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 'current';
961
+ var messagesToAdd = newMessages;
962
+ var targetMessageSetIndex;
963
+
964
+ if (addIfDoesNotExist) {
965
+ var overlappingMessageSetIndices = this.messageSets.map(function (_, i) {
966
+ return i;
967
+ }).filter(function (i) {
968
+ return _this5.areMessageSetsOverlap(_this5.messageSets[i].messages, newMessages);
969
+ });
970
+
971
+ switch (messageSetToAddToIfDoesNotExist) {
972
+ case 'new':
973
+ if (overlappingMessageSetIndices.length > 0) {
974
+ targetMessageSetIndex = overlappingMessageSetIndices[0]; // No new message set is created if newMessages only contains thread replies
975
+ } else if (newMessages.some(function (m) {
976
+ return !m.parent_id;
977
+ })) {
978
+ this.messageSets.push({
979
+ messages: [],
980
+ isCurrent: false,
981
+ isLatest: false
982
+ });
983
+ targetMessageSetIndex = this.messageSets.length - 1;
984
+ }
985
+
986
+ break;
987
+
988
+ case 'current':
989
+ targetMessageSetIndex = this.messageSets.findIndex(function (s) {
990
+ return s.isCurrent;
991
+ });
992
+ break;
993
+
994
+ case 'latest':
995
+ targetMessageSetIndex = this.messageSets.findIndex(function (s) {
996
+ return s.isLatest;
997
+ });
998
+ break;
999
+
1000
+ default:
1001
+ targetMessageSetIndex = -1;
1002
+ } // when merging the target set will be the first one from the overlapping message sets
1003
+
1004
+
1005
+ var mergeTargetMessageSetIndex = overlappingMessageSetIndices.splice(0, 1)[0];
1006
+
1007
+ var mergeSourceMessageSetIndices = _toConsumableArray__default['default'](overlappingMessageSetIndices);
1008
+
1009
+ if (mergeTargetMessageSetIndex !== undefined && mergeTargetMessageSetIndex !== targetMessageSetIndex) {
1010
+ mergeSourceMessageSetIndices.push(targetMessageSetIndex);
1011
+ } // merge message sets
1012
+
1013
+
1014
+ if (mergeSourceMessageSetIndices.length > 0) {
1015
+ var target = this.messageSets[mergeTargetMessageSetIndex];
1016
+ var sources = this.messageSets.filter(function (_, i) {
1017
+ return mergeSourceMessageSetIndices.indexOf(i) !== -1;
1018
+ });
1019
+ sources.forEach(function (messageSet) {
1020
+ target.isLatest = target.isLatest || messageSet.isLatest;
1021
+ target.isCurrent = target.isCurrent || messageSet.isCurrent;
1022
+ messagesToAdd = [].concat(_toConsumableArray__default['default'](messagesToAdd), _toConsumableArray__default['default'](messageSet.messages));
1023
+ });
1024
+ sources.forEach(function (s) {
1025
+ return _this5.messageSets.splice(_this5.messageSets.indexOf(s), 1);
1026
+ });
1027
+ var overlappingMessageSetIndex = this.messageSets.findIndex(function (s) {
1028
+ return _this5.areMessageSetsOverlap(s.messages, newMessages);
1029
+ });
1030
+ targetMessageSetIndex = overlappingMessageSetIndex;
1031
+ }
1032
+ } else {
1033
+ // assumes that all new messages belong to the same set
1034
+ targetMessageSetIndex = this.findMessageSetIndex(newMessages[0]);
1035
+ }
1036
+
1037
+ return {
1038
+ targetMessageSetIndex: targetMessageSetIndex,
1039
+ messagesToAdd: messagesToAdd
1040
+ };
1041
+ }
728
1042
  }]);
729
1043
 
730
1044
  return ChannelState;
@@ -1087,7 +1401,7 @@ var Channel = /*#__PURE__*/function () {
1087
1401
  presence: false
1088
1402
  };
1089
1403
  _context.next = 3;
1090
- return _this.query(options);
1404
+ return _this.query(options, 'latest');
1091
1405
 
1092
1406
  case 3:
1093
1407
  return _context.abrupt("return", _context.sent);
@@ -2385,14 +2699,14 @@ var Channel = /*#__PURE__*/function () {
2385
2699
  value: function lastMessage() {
2386
2700
  // get last 5 messages, sort, return the latest
2387
2701
  // get a slice of the last 5
2388
- var min = this.state.messages.length - 5;
2702
+ var min = this.state.latestMessages.length - 5;
2389
2703
 
2390
2704
  if (min < 0) {
2391
2705
  min = 0;
2392
2706
  }
2393
2707
 
2394
- var max = this.state.messages.length + 1;
2395
- var messageSlice = this.state.messages.slice(min, max); // sort by pk desc
2708
+ var max = this.state.latestMessages.length + 1;
2709
+ var messageSlice = this.state.latestMessages.slice(min, max); // sort by pk desc
2396
2710
 
2397
2711
  messageSlice.sort(function (a, b) {
2398
2712
  return b.created_at.getTime() - a.created_at.getTime();
@@ -2501,7 +2815,7 @@ var Channel = /*#__PURE__*/function () {
2501
2815
 
2502
2816
  combined = _objectSpread$5(_objectSpread$5({}, defaultOptions), options);
2503
2817
  _context27.next = 7;
2504
- return this.query(combined);
2818
+ return this.query(combined, 'latest');
2505
2819
 
2506
2820
  case 7:
2507
2821
  state = _context27.sent;
@@ -2575,7 +2889,7 @@ var Channel = /*#__PURE__*/function () {
2575
2889
  * getReplies - List the message replies for a parent message
2576
2890
  *
2577
2891
  * @param {string} parent_id The message parent id, ie the top of the thread
2578
- * @param {PaginationOptions & { user?: UserResponse<StreamChatGenerics>; user_id?: string }} options Pagination params, ie {limit:10, id_lte: 10}
2892
+ * @param {MessagePaginationOptions & { user?: UserResponse<StreamChatGenerics>; user_id?: string }} options Pagination params, ie {limit:10, id_lte: 10}
2579
2893
  *
2580
2894
  * @return {Promise<GetRepliesAPIResponse<StreamChatGenerics>>} A response with a list of messages
2581
2895
  */
@@ -2736,8 +3050,8 @@ var Channel = /*#__PURE__*/function () {
2736
3050
  if (!lastRead) return this.state.unreadCount;
2737
3051
  var count = 0;
2738
3052
 
2739
- for (var i = 0; i < this.state.messages.length; i += 1) {
2740
- var message = this.state.messages[i];
3053
+ for (var i = 0; i < this.state.latestMessages.length; i += 1) {
3054
+ var message = this.state.latestMessages[i];
2741
3055
 
2742
3056
  if (message.created_at > lastRead && this._countMessageAsUnread(message)) {
2743
3057
  count++;
@@ -2747,7 +3061,7 @@ var Channel = /*#__PURE__*/function () {
2747
3061
  return count;
2748
3062
  }
2749
3063
  /**
2750
- * countUnread - Count the number of unread messages mentioning the current user
3064
+ * countUnreadMentions - Count the number of unread messages mentioning the current user
2751
3065
  *
2752
3066
  * @return {number} Unread mentions count
2753
3067
  */
@@ -2759,10 +3073,10 @@ var Channel = /*#__PURE__*/function () {
2759
3073
  var userID = this.getClient().userID;
2760
3074
  var count = 0;
2761
3075
 
2762
- for (var i = 0; i < this.state.messages.length; i += 1) {
3076
+ for (var i = 0; i < this.state.latestMessages.length; i += 1) {
2763
3077
  var _message$mentioned_us;
2764
3078
 
2765
- var message = this.state.messages[i];
3079
+ var message = this.state.latestMessages[i];
2766
3080
 
2767
3081
  if (this._countMessageAsUnread(message) && (!lastRead || message.created_at > lastRead) && (_message$mentioned_us = message.mentioned_users) !== null && _message$mentioned_us !== void 0 && _message$mentioned_us.some(function (user) {
2768
3082
  return user.id === userID;
@@ -2786,33 +3100,40 @@ var Channel = /*#__PURE__*/function () {
2786
3100
  * query - Query the API, get messages, members or other channel fields
2787
3101
  *
2788
3102
  * @param {ChannelQueryOptions<StreamChatGenerics>} options The query options
3103
+ * @param {MessageSetType} messageSetToAddToIfDoesNotExist It's possible to load disjunct sets of a channel's messages into state, use `current` to load the initial channel state or if you want to extend the currently displayed messages, use `latest` if you want to load/extend the latest messages, `new` is used for loading a specific message and it's surroundings
2789
3104
  *
2790
3105
  * @return {Promise<ChannelAPIResponse<StreamChatGenerics>>} Returns a query response
2791
3106
  */
2792
3107
  function () {
2793
3108
  var _query = _asyncToGenerator__default['default']( /*#__PURE__*/_regeneratorRuntime__default['default'].mark(function _callee31(options) {
2794
- var queryURL, state, membersStr, tempChannelCid;
3109
+ var messageSetToAddToIfDoesNotExist,
3110
+ queryURL,
3111
+ state,
3112
+ membersStr,
3113
+ tempChannelCid,
3114
+ _args31 = arguments;
2795
3115
  return _regeneratorRuntime__default['default'].wrap(function _callee31$(_context31) {
2796
3116
  while (1) {
2797
3117
  switch (_context31.prev = _context31.next) {
2798
3118
  case 0:
2799
- _context31.next = 2;
3119
+ messageSetToAddToIfDoesNotExist = _args31.length > 1 && _args31[1] !== undefined ? _args31[1] : 'current';
3120
+ _context31.next = 3;
2800
3121
  return this.getClient().wsPromise;
2801
3122
 
2802
- case 2:
3123
+ case 3:
2803
3124
  queryURL = "".concat(this.getClient().baseURL, "/channels/").concat(this.type);
2804
3125
 
2805
3126
  if (this.id) {
2806
3127
  queryURL += "/".concat(this.id);
2807
3128
  }
2808
3129
 
2809
- _context31.next = 6;
3130
+ _context31.next = 7;
2810
3131
  return this.getClient().post(queryURL + '/query', _objectSpread$5({
2811
3132
  data: this._data,
2812
3133
  state: true
2813
3134
  }, options));
2814
3135
 
2815
- case 6:
3136
+ case 7:
2816
3137
  state = _context31.sent;
2817
3138
 
2818
3139
  // update the channel id if it was missing
@@ -2841,11 +3162,11 @@ var Channel = /*#__PURE__*/function () {
2841
3162
  this.getClient()._addChannelConfig(state); // add any messages to our channel state
2842
3163
 
2843
3164
 
2844
- this._initializeState(state);
3165
+ this._initializeState(state, messageSetToAddToIfDoesNotExist);
2845
3166
 
2846
3167
  return _context31.abrupt("return", state);
2847
3168
 
2848
- case 11:
3169
+ case 12:
2849
3170
  case "end":
2850
3171
  return _context31.stop();
2851
3172
  }
@@ -3395,6 +3716,8 @@ var Channel = /*#__PURE__*/function () {
3395
3716
  }, {
3396
3717
  key: "_initializeState",
3397
3718
  value: function _initializeState(state) {
3719
+ var messageSetToAddToIfDoesNotExist = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'latest';
3720
+
3398
3721
  var _this$getClient2 = this.getClient(),
3399
3722
  clientState = _this$getClient2.state,
3400
3723
  user = _this$getClient2.user,
@@ -3424,10 +3747,10 @@ var Channel = /*#__PURE__*/function () {
3424
3747
  var messages = state.messages || [];
3425
3748
 
3426
3749
  if (!this.state.messages) {
3427
- this.state.messages = [];
3750
+ this.state.initMessages();
3428
3751
  }
3429
3752
 
3430
- this.state.addMessagesSorted(messages, false, true);
3753
+ this.state.addMessagesSorted(messages, false, true, true, messageSetToAddToIfDoesNotExist);
3431
3754
 
3432
3755
  if (!this.state.pinnedMessages) {
3433
3756
  this.state.pinnedMessages = [];
@@ -7467,11 +7790,11 @@ var StreamChat = /*#__PURE__*/function () {
7467
7790
  c.initialized = true;
7468
7791
 
7469
7792
  if (skipInitialization === undefined) {
7470
- c._initializeState(_channelState);
7793
+ c._initializeState(_channelState, 'latest');
7471
7794
  } else if (!skipInitialization.includes(_channelState.channel.id)) {
7472
7795
  c.state.clearMessages();
7473
7796
 
7474
- c._initializeState(_channelState);
7797
+ c._initializeState(_channelState, 'latest');
7475
7798
  }
7476
7799
 
7477
7800
  channels.push(c);
@@ -9206,7 +9529,7 @@ var StreamChat = /*#__PURE__*/function () {
9206
9529
  }, {
9207
9530
  key: "getUserAgent",
9208
9531
  value: function getUserAgent() {
9209
- return this.userAgent || "stream-chat-javascript-client-".concat(this.node ? 'node' : 'browser', "-", "6.2.0");
9532
+ return this.userAgent || "stream-chat-javascript-client-".concat(this.node ? 'node' : 'browser', "-", "6.3.0");
9210
9533
  }
9211
9534
  }, {
9212
9535
  key: "setUserAgent",
@@ -10376,6 +10699,122 @@ var StreamChat = /*#__PURE__*/function () {
10376
10699
 
10377
10700
  return _listImports;
10378
10701
  }()
10702
+ /**
10703
+ * upsertPushProvider - Create or Update a push provider
10704
+ *
10705
+ * Note: Works only for v2 push version is enabled on app settings.
10706
+ *
10707
+ * @param {PushProviderConfig} configuration of the provider you want to create or update
10708
+ *
10709
+ * @return {APIResponse & PushProviderUpsertResponse} A push provider
10710
+ */
10711
+
10712
+ }, {
10713
+ key: "upsertPushProvider",
10714
+ value: function () {
10715
+ var _upsertPushProvider = _asyncToGenerator__default['default']( /*#__PURE__*/_regeneratorRuntime__default['default'].mark(function _callee75(pushProvider) {
10716
+ return _regeneratorRuntime__default['default'].wrap(function _callee75$(_context75) {
10717
+ while (1) {
10718
+ switch (_context75.prev = _context75.next) {
10719
+ case 0:
10720
+ _context75.next = 2;
10721
+ return this.post(this.baseURL + "/push_providers", {
10722
+ push_provider: pushProvider
10723
+ });
10724
+
10725
+ case 2:
10726
+ return _context75.abrupt("return", _context75.sent);
10727
+
10728
+ case 3:
10729
+ case "end":
10730
+ return _context75.stop();
10731
+ }
10732
+ }
10733
+ }, _callee75, this);
10734
+ }));
10735
+
10736
+ function upsertPushProvider(_x98) {
10737
+ return _upsertPushProvider.apply(this, arguments);
10738
+ }
10739
+
10740
+ return upsertPushProvider;
10741
+ }()
10742
+ /**
10743
+ * deletePushProvider - Delete a push provider
10744
+ *
10745
+ * Note: Works only for v2 push version is enabled on app settings.
10746
+ *
10747
+ * @param {PushProviderID} type and foreign id of the push provider to be deleted
10748
+ *
10749
+ * @return {APIResponse} An API response
10750
+ */
10751
+
10752
+ }, {
10753
+ key: "deletePushProvider",
10754
+ value: function () {
10755
+ var _deletePushProvider = _asyncToGenerator__default['default']( /*#__PURE__*/_regeneratorRuntime__default['default'].mark(function _callee76(_ref8) {
10756
+ var type, name;
10757
+ return _regeneratorRuntime__default['default'].wrap(function _callee76$(_context76) {
10758
+ while (1) {
10759
+ switch (_context76.prev = _context76.next) {
10760
+ case 0:
10761
+ type = _ref8.type, name = _ref8.name;
10762
+ _context76.next = 3;
10763
+ return this.delete(this.baseURL + "/push_providers/".concat(type, "/").concat(name));
10764
+
10765
+ case 3:
10766
+ return _context76.abrupt("return", _context76.sent);
10767
+
10768
+ case 4:
10769
+ case "end":
10770
+ return _context76.stop();
10771
+ }
10772
+ }
10773
+ }, _callee76, this);
10774
+ }));
10775
+
10776
+ function deletePushProvider(_x99) {
10777
+ return _deletePushProvider.apply(this, arguments);
10778
+ }
10779
+
10780
+ return deletePushProvider;
10781
+ }()
10782
+ /**
10783
+ * listPushProviders - Get all push providers in the app
10784
+ *
10785
+ * Note: Works only for v2 push version is enabled on app settings.
10786
+ *
10787
+ * @return {APIResponse & PushProviderListResponse} A push provider
10788
+ */
10789
+
10790
+ }, {
10791
+ key: "listPushProviders",
10792
+ value: function () {
10793
+ var _listPushProviders = _asyncToGenerator__default['default']( /*#__PURE__*/_regeneratorRuntime__default['default'].mark(function _callee77() {
10794
+ return _regeneratorRuntime__default['default'].wrap(function _callee77$(_context77) {
10795
+ while (1) {
10796
+ switch (_context77.prev = _context77.next) {
10797
+ case 0:
10798
+ _context77.next = 2;
10799
+ return this.get(this.baseURL + "/push_providers");
10800
+
10801
+ case 2:
10802
+ return _context77.abrupt("return", _context77.sent);
10803
+
10804
+ case 3:
10805
+ case "end":
10806
+ return _context77.stop();
10807
+ }
10808
+ }
10809
+ }, _callee77, this);
10810
+ }));
10811
+
10812
+ function listPushProviders() {
10813
+ return _listPushProviders.apply(this, arguments);
10814
+ }
10815
+
10816
+ return listPushProviders;
10817
+ }()
10379
10818
  }], [{
10380
10819
  key: "getInstance",
10381
10820
  value: function getInstance(key, secretOrOptions, options) {