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/browser.js CHANGED
@@ -122,6 +122,13 @@ var ChannelState = /*#__PURE__*/function () {
122
122
  * When false, any new message (received by websocket event - message.new) will not
123
123
  * be pushed on to message list.
124
124
  */
125
+
126
+ /**
127
+ * Disjoint lists of messages
128
+ * Users can jump in the message list (with searching) and this can result in disjoint lists of messages
129
+ * The state manages these lists and merges them when lists overlap
130
+ * The messages array contains the currently active set
131
+ */
125
132
  function ChannelState(channel) {
126
133
  var _this = this,
127
134
  _channel$state;
@@ -136,8 +143,6 @@ var ChannelState = /*#__PURE__*/function () {
136
143
 
137
144
  _defineProperty__default['default'](this, "read", void 0);
138
145
 
139
- _defineProperty__default['default'](this, "messages", void 0);
140
-
141
146
  _defineProperty__default['default'](this, "pinnedMessages", void 0);
142
147
 
143
148
  _defineProperty__default['default'](this, "threads", void 0);
@@ -156,6 +161,8 @@ var ChannelState = /*#__PURE__*/function () {
156
161
 
157
162
  _defineProperty__default['default'](this, "isUpToDate", void 0);
158
163
 
164
+ _defineProperty__default['default'](this, "messageSets", []);
165
+
159
166
  _defineProperty__default['default'](this, "setIsUpToDate", function (isUpToDate) {
160
167
  _this.isUpToDate = isUpToDate;
161
168
  });
@@ -185,7 +192,9 @@ var ChannelState = /*#__PURE__*/function () {
185
192
  }
186
193
  };
187
194
 
188
- _updateUserMessages(_this.messages, user);
195
+ _this.messageSets.forEach(function (set) {
196
+ return _updateUserMessages(set.messages, user);
197
+ });
189
198
 
190
199
  for (var parentId in _this.threads) {
191
200
  _updateUserMessages(_this.threads[parentId], user);
@@ -239,7 +248,9 @@ var ChannelState = /*#__PURE__*/function () {
239
248
  }
240
249
  };
241
250
 
242
- _deleteUserMessages(_this.messages, user, hardDelete);
251
+ _this.messageSets.forEach(function (set) {
252
+ return _deleteUserMessages(set.messages, user, hardDelete);
253
+ });
243
254
 
244
255
  for (var parentId in _this.threads) {
245
256
  _deleteUserMessages(_this.threads[parentId], user, hardDelete);
@@ -252,7 +263,7 @@ var ChannelState = /*#__PURE__*/function () {
252
263
  this.watcher_count = 0;
253
264
  this.typing = {};
254
265
  this.read = {};
255
- this.messages = [];
266
+ this.initMessages();
256
267
  this.pinnedMessages = [];
257
268
  this.threads = {}; // a list of users to hide messages from
258
269
 
@@ -271,22 +282,58 @@ var ChannelState = /*#__PURE__*/function () {
271
282
  this.isUpToDate = true;
272
283
  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;
273
284
  }
274
- /**
275
- * addMessageSorted - Add a message to the state
276
- *
277
- * @param {MessageResponse<StreamChatGenerics>} newMessage A new message
278
- * @param {boolean} timestampChanged Whether updating a message with changed created_at value.
279
- * @param {boolean} addIfDoesNotExist Add message if it is not in the list, used to prevent out of order updated messages from being added.
280
- *
281
- */
282
-
283
285
 
284
286
  _createClass__default['default'](ChannelState, [{
287
+ key: "messages",
288
+ get: function get() {
289
+ var _this$messageSets$fin;
290
+
291
+ return ((_this$messageSets$fin = this.messageSets.find(function (s) {
292
+ return s.isCurrent;
293
+ })) === null || _this$messageSets$fin === void 0 ? void 0 : _this$messageSets$fin.messages) || [];
294
+ },
295
+ set: function set(messages) {
296
+ var index = this.messageSets.findIndex(function (s) {
297
+ return s.isCurrent;
298
+ });
299
+ this.messageSets[index].messages = messages;
300
+ }
301
+ /**
302
+ * The list of latest messages
303
+ * 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)
304
+ */
305
+
306
+ }, {
307
+ key: "latestMessages",
308
+ get: function get() {
309
+ var _this$messageSets$fin2;
310
+
311
+ return ((_this$messageSets$fin2 = this.messageSets.find(function (s) {
312
+ return s.isLatest;
313
+ })) === null || _this$messageSets$fin2 === void 0 ? void 0 : _this$messageSets$fin2.messages) || [];
314
+ },
315
+ set: function set(messages) {
316
+ var index = this.messageSets.findIndex(function (s) {
317
+ return s.isLatest;
318
+ });
319
+ this.messageSets[index].messages = messages;
320
+ }
321
+ /**
322
+ * addMessageSorted - Add a message to the state
323
+ *
324
+ * @param {MessageResponse<StreamChatGenerics>} newMessage A new message
325
+ * @param {boolean} timestampChanged Whether updating a message with changed created_at value.
326
+ * @param {boolean} addIfDoesNotExist Add message if it is not in the list, used to prevent out of order updated messages from being added.
327
+ * @param {MessageSetType} messageSetToAddToIfDoesNotExist Which message set to add to if message is not in the list (only used if addIfDoesNotExist is true)
328
+ */
329
+
330
+ }, {
285
331
  key: "addMessageSorted",
286
332
  value: function addMessageSorted(newMessage) {
287
333
  var timestampChanged = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
288
334
  var addIfDoesNotExist = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true;
289
- return this.addMessagesSorted([newMessage], timestampChanged, false, addIfDoesNotExist);
335
+ var messageSetToAddToIfDoesNotExist = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 'latest';
336
+ return this.addMessagesSorted([newMessage], timestampChanged, false, addIfDoesNotExist, messageSetToAddToIfDoesNotExist);
290
337
  }
291
338
  /**
292
339
  * formatMessage - Takes the message object. Parses the dates, sets __html
@@ -318,6 +365,7 @@ var ChannelState = /*#__PURE__*/function () {
318
365
  * @param {boolean} timestampChanged Whether updating messages with changed created_at value.
319
366
  * @param {boolean} initializing Whether channel is being initialized.
320
367
  * @param {boolean} addIfDoesNotExist Add message if it is not in the list, used to prevent out of order updated messages from being added.
368
+ * @param {MessageSetType} messageSetToAddToIfDoesNotExist Which message set to add to if messages are not in the list (only used if addIfDoesNotExist is true)
321
369
  *
322
370
  */
323
371
 
@@ -327,48 +375,60 @@ var ChannelState = /*#__PURE__*/function () {
327
375
  var timestampChanged = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
328
376
  var initializing = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
329
377
  var addIfDoesNotExist = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : true;
378
+ var messageSetToAddToIfDoesNotExist = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 'current';
330
379
 
331
- for (var i = 0; i < newMessages.length; i += 1) {
332
- var _this$_channel;
380
+ var _this$findTargetMessa = this.findTargetMessageSet(newMessages, addIfDoesNotExist, messageSetToAddToIfDoesNotExist),
381
+ messagesToAdd = _this$findTargetMessa.messagesToAdd,
382
+ targetMessageSetIndex = _this$findTargetMessa.targetMessageSetIndex;
333
383
 
334
- var isFromShadowBannedUser = newMessages[i].shadowed;
384
+ for (var i = 0; i < messagesToAdd.length; i += 1) {
385
+ var isFromShadowBannedUser = messagesToAdd[i].shadowed;
335
386
 
336
387
  if (isFromShadowBannedUser) {
337
388
  continue;
338
389
  }
339
390
 
340
- var message = this.formatMessage(newMessages[i]);
391
+ var isMerging = messagesToAdd[i].created_at instanceof Date;
392
+ var message = void 0;
341
393
 
342
- if (message.user && (_this$_channel = this._channel) !== null && _this$_channel !== void 0 && _this$_channel.cid) {
343
- /**
344
- * Store the reference to user for this channel, so that when we have to
345
- * handle updates to user, we can use the reference map, to determine which
346
- * channels need to be updated with updated user object.
347
- */
348
- this._channel.getClient().state.updateUserReference(message.user, this._channel.cid);
349
- }
394
+ if (isMerging) {
395
+ message = messagesToAdd[i];
396
+ } else {
397
+ var _this$_channel;
350
398
 
351
- if (initializing && message.id && this.threads[message.id]) {
352
- // If we are initializing the state of channel (e.g., in case of connection recovery),
353
- // then in that case we remove thread related to this message from threads object.
354
- // This way we can ensure that we don't have any stale data in thread object
355
- // and consumer can refetch the replies.
356
- delete this.threads[message.id];
357
- }
399
+ message = this.formatMessage(messagesToAdd[i]);
358
400
 
359
- if (!this.last_message_at) {
360
- this.last_message_at = new Date(message.created_at.getTime());
361
- }
401
+ if (message.user && (_this$_channel = this._channel) !== null && _this$_channel !== void 0 && _this$_channel.cid) {
402
+ /**
403
+ * Store the reference to user for this channel, so that when we have to
404
+ * handle updates to user, we can use the reference map, to determine which
405
+ * channels need to be updated with updated user object.
406
+ */
407
+ this._channel.getClient().state.updateUserReference(message.user, this._channel.cid);
408
+ }
409
+
410
+ if (initializing && message.id && this.threads[message.id]) {
411
+ // If we are initializing the state of channel (e.g., in case of connection recovery),
412
+ // then in that case we remove thread related to this message from threads object.
413
+ // This way we can ensure that we don't have any stale data in thread object
414
+ // and consumer can refetch the replies.
415
+ delete this.threads[message.id];
416
+ }
362
417
 
363
- if (message.created_at.getTime() > this.last_message_at.getTime()) {
364
- this.last_message_at = new Date(message.created_at.getTime());
418
+ if (!this.last_message_at) {
419
+ this.last_message_at = new Date(message.created_at.getTime());
420
+ }
421
+
422
+ if (message.created_at.getTime() > this.last_message_at.getTime()) {
423
+ this.last_message_at = new Date(message.created_at.getTime());
424
+ }
365
425
  } // update or append the messages...
366
426
 
367
427
 
368
- var parentID = message.parent_id; // add to the main message list
428
+ var parentID = message.parent_id; // add to the given message set
369
429
 
370
- if (!parentID || message.show_in_channel) {
371
- this.messages = this._addToMessageList(this.messages, message, timestampChanged, 'created_at', addIfDoesNotExist);
430
+ if ((!parentID || message.show_in_channel) && targetMessageSetIndex !== -1) {
431
+ this.messageSets[targetMessageSetIndex].messages = this._addToMessageList(this.messageSets[targetMessageSetIndex].messages, message, timestampChanged, 'created_at', addIfDoesNotExist);
372
432
  }
373
433
  /**
374
434
  * Add message to thread if applicable and the message
@@ -381,7 +441,7 @@ var ChannelState = /*#__PURE__*/function () {
381
441
  */
382
442
 
383
443
 
384
- if (parentID && !initializing) {
444
+ if (parentID && !initializing && !isMerging) {
385
445
  var thread = this.threads[parentID] || [];
386
446
 
387
447
  var threadMessages = this._addToMessageList(thread, message, timestampChanged, 'created_at', addIfDoesNotExist);
@@ -492,6 +552,8 @@ var ChannelState = /*#__PURE__*/function () {
492
552
  }, {
493
553
  key: "removeQuotedMessageReferences",
494
554
  value: function removeQuotedMessageReferences(message) {
555
+ var _this4 = this;
556
+
495
557
  var parseMessage = function parseMessage(m) {
496
558
  var _m$pinned_at, _m$updated_at;
497
559
 
@@ -502,16 +564,19 @@ var ChannelState = /*#__PURE__*/function () {
502
564
  });
503
565
  };
504
566
 
505
- var updatedMessages = this.messages.filter(function (msg) {
506
- return msg.quoted_message_id === message.id;
507
- }).map(parseMessage).map(function (msg) {
508
- return _objectSpread$7(_objectSpread$7({}, msg), {}, {
509
- quoted_message: _objectSpread$7(_objectSpread$7({}, message), {}, {
510
- attachments: []
511
- })
567
+ this.messageSets.forEach(function (set) {
568
+ var updatedMessages = set.messages.filter(function (msg) {
569
+ return msg.quoted_message_id === message.id;
570
+ }).map(parseMessage).map(function (msg) {
571
+ return _objectSpread$7(_objectSpread$7({}, msg), {}, {
572
+ quoted_message: _objectSpread$7(_objectSpread$7({}, message), {}, {
573
+ attachments: []
574
+ })
575
+ });
512
576
  });
577
+
578
+ _this4.addMessagesSorted(updatedMessages, true);
513
579
  });
514
- this.addMessagesSorted(updatedMessages, true);
515
580
  }
516
581
  /**
517
582
  * Updates all instances of given message in channel state
@@ -539,12 +604,16 @@ var ChannelState = /*#__PURE__*/function () {
539
604
  }
540
605
 
541
606
  if (!show_in_channel && !parent_id || show_in_channel) {
542
- var _msgIndex = this.messages.findIndex(function (msg) {
543
- return msg.id === message.id;
544
- });
607
+ var messageSetIndex = this.findMessageSetIndex(message);
608
+
609
+ if (messageSetIndex !== -1) {
610
+ var _msgIndex = this.messageSets[messageSetIndex].messages.findIndex(function (msg) {
611
+ return msg.id === message.id;
612
+ });
545
613
 
546
- if (_msgIndex !== -1) {
547
- this.messages[_msgIndex] = updateFunc(this.messages[_msgIndex]);
614
+ if (_msgIndex !== -1) {
615
+ this.messageSets[messageSetIndex].messages[_msgIndex] = updateFunc(this.messageSets[messageSetIndex].messages[_msgIndex]);
616
+ }
548
617
  }
549
618
  }
550
619
 
@@ -663,12 +732,16 @@ var ChannelState = /*#__PURE__*/function () {
663
732
  this.threads[messageToRemove.parent_id] = threadMessages;
664
733
  isRemoved = removed;
665
734
  } else {
666
- var _this$removeMessageFr3 = this.removeMessageFromArray(this.messages, messageToRemove),
667
- _removed = _this$removeMessageFr3.removed,
668
- messages = _this$removeMessageFr3.result;
735
+ var messageSetIndex = this.findMessageSetIndex(messageToRemove);
669
736
 
670
- this.messages = messages;
671
- isRemoved = _removed;
737
+ if (messageSetIndex !== -1) {
738
+ var _this$removeMessageFr3 = this.removeMessageFromArray(this.messageSets[messageSetIndex].messages, messageToRemove),
739
+ _removed = _this$removeMessageFr3.removed,
740
+ messages = _this$removeMessageFr3.result;
741
+
742
+ this.messageSets[messageSetIndex].messages = messages;
743
+ isRemoved = _removed;
744
+ }
672
745
  }
673
746
 
674
747
  return isRemoved;
@@ -681,10 +754,10 @@ var ChannelState = /*#__PURE__*/function () {
681
754
  *
682
755
  */
683
756
  function filterErrorMessages() {
684
- var filteredMessages = this.messages.filter(function (message) {
757
+ var filteredMessages = this.latestMessages.filter(function (message) {
685
758
  return message.type !== 'error';
686
759
  });
687
- this.messages = filteredMessages;
760
+ this.latestMessages = filteredMessages;
688
761
  }
689
762
  /**
690
763
  * clean - Remove stale data such as users that stayed in typing state for more than 5 seconds
@@ -718,9 +791,250 @@ var ChannelState = /*#__PURE__*/function () {
718
791
  }, {
719
792
  key: "clearMessages",
720
793
  value: function clearMessages() {
721
- this.messages = [];
794
+ this.initMessages();
722
795
  this.pinnedMessages = [];
723
796
  }
797
+ }, {
798
+ key: "initMessages",
799
+ value: function initMessages() {
800
+ this.messageSets = [{
801
+ messages: [],
802
+ isLatest: true,
803
+ isCurrent: true
804
+ }];
805
+ }
806
+ /**
807
+ * loadMessageIntoState - Loads a given message (and messages around it) into the state
808
+ *
809
+ * @param {string} messageId The id of the message, or 'latest' to indicate switching to the latest messages
810
+ * @param {string} parentMessageId The id of the parent message, if we want load a thread reply
811
+ */
812
+
813
+ }, {
814
+ key: "loadMessageIntoState",
815
+ value: function () {
816
+ var _loadMessageIntoState = _asyncToGenerator__default['default']( /*#__PURE__*/_regeneratorRuntime__default['default'].mark(function _callee(messageId, parentMessageId) {
817
+ var _this$threads$parentM;
818
+
819
+ var messageSetIndex, switchedToMessageSet, loadedMessageThread, messageIdToFind;
820
+ return _regeneratorRuntime__default['default'].wrap(function _callee$(_context) {
821
+ while (1) {
822
+ switch (_context.prev = _context.next) {
823
+ case 0:
824
+ switchedToMessageSet = false;
825
+ loadedMessageThread = false;
826
+ messageIdToFind = parentMessageId || messageId;
827
+
828
+ if (!(messageId === 'latest')) {
829
+ _context.next = 9;
830
+ break;
831
+ }
832
+
833
+ if (!(this.messages === this.latestMessages)) {
834
+ _context.next = 6;
835
+ break;
836
+ }
837
+
838
+ return _context.abrupt("return");
839
+
840
+ case 6:
841
+ messageSetIndex = this.messageSets.findIndex(function (s) {
842
+ return s.isLatest;
843
+ });
844
+ _context.next = 10;
845
+ break;
846
+
847
+ case 9:
848
+ messageSetIndex = this.findMessageSetIndex({
849
+ id: messageIdToFind
850
+ });
851
+
852
+ case 10:
853
+ if (messageSetIndex !== -1) {
854
+ this.switchToMessageSet(messageSetIndex);
855
+ switchedToMessageSet = true;
856
+ }
857
+
858
+ loadedMessageThread = !parentMessageId || !!((_this$threads$parentM = this.threads[parentMessageId]) !== null && _this$threads$parentM !== void 0 && _this$threads$parentM.find(function (m) {
859
+ return m.id === messageId;
860
+ }));
861
+
862
+ if (!(switchedToMessageSet && loadedMessageThread)) {
863
+ _context.next = 14;
864
+ break;
865
+ }
866
+
867
+ return _context.abrupt("return");
868
+
869
+ case 14:
870
+ if (switchedToMessageSet) {
871
+ _context.next = 17;
872
+ break;
873
+ }
874
+
875
+ _context.next = 17;
876
+ return this._channel.query({
877
+ messages: {
878
+ id_around: messageIdToFind,
879
+ limit: 25
880
+ }
881
+ }, 'new');
882
+
883
+ case 17:
884
+ if (!(!loadedMessageThread && parentMessageId)) {
885
+ _context.next = 20;
886
+ break;
887
+ }
888
+
889
+ _context.next = 20;
890
+ return this._channel.getReplies(parentMessageId, {
891
+ id_around: messageId,
892
+ limit: 25
893
+ });
894
+
895
+ case 20:
896
+ messageSetIndex = this.findMessageSetIndex({
897
+ id: messageIdToFind
898
+ });
899
+
900
+ if (messageSetIndex !== -1) {
901
+ this.switchToMessageSet(messageSetIndex);
902
+ }
903
+
904
+ case 22:
905
+ case "end":
906
+ return _context.stop();
907
+ }
908
+ }
909
+ }, _callee, this);
910
+ }));
911
+
912
+ function loadMessageIntoState(_x, _x2) {
913
+ return _loadMessageIntoState.apply(this, arguments);
914
+ }
915
+
916
+ return loadMessageIntoState;
917
+ }()
918
+ }, {
919
+ key: "switchToMessageSet",
920
+ value: function switchToMessageSet(index) {
921
+ var currentMessages = this.messageSets.find(function (s) {
922
+ return s.isCurrent;
923
+ });
924
+
925
+ if (!currentMessages) {
926
+ return;
927
+ }
928
+
929
+ currentMessages.isCurrent = false;
930
+ this.messageSets[index].isCurrent = true;
931
+ }
932
+ }, {
933
+ key: "areMessageSetsOverlap",
934
+ value: function areMessageSetsOverlap(messages1, messages2) {
935
+ return messages1.some(function (m1) {
936
+ return messages2.find(function (m2) {
937
+ return m1.id === m2.id;
938
+ });
939
+ });
940
+ }
941
+ }, {
942
+ key: "findMessageSetIndex",
943
+ value: function findMessageSetIndex(message) {
944
+ return this.messageSets.findIndex(function (set) {
945
+ return !!set.messages.find(function (m) {
946
+ return m.id === message.id;
947
+ });
948
+ });
949
+ }
950
+ }, {
951
+ key: "findTargetMessageSet",
952
+ value: function findTargetMessageSet(newMessages) {
953
+ var _this5 = this;
954
+
955
+ var addIfDoesNotExist = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
956
+ var messageSetToAddToIfDoesNotExist = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 'current';
957
+ var messagesToAdd = newMessages;
958
+ var targetMessageSetIndex;
959
+
960
+ if (addIfDoesNotExist) {
961
+ var overlappingMessageSetIndices = this.messageSets.map(function (_, i) {
962
+ return i;
963
+ }).filter(function (i) {
964
+ return _this5.areMessageSetsOverlap(_this5.messageSets[i].messages, newMessages);
965
+ });
966
+
967
+ switch (messageSetToAddToIfDoesNotExist) {
968
+ case 'new':
969
+ if (overlappingMessageSetIndices.length > 0) {
970
+ targetMessageSetIndex = overlappingMessageSetIndices[0]; // No new message set is created if newMessages only contains thread replies
971
+ } else if (newMessages.some(function (m) {
972
+ return !m.parent_id;
973
+ })) {
974
+ this.messageSets.push({
975
+ messages: [],
976
+ isCurrent: false,
977
+ isLatest: false
978
+ });
979
+ targetMessageSetIndex = this.messageSets.length - 1;
980
+ }
981
+
982
+ break;
983
+
984
+ case 'current':
985
+ targetMessageSetIndex = this.messageSets.findIndex(function (s) {
986
+ return s.isCurrent;
987
+ });
988
+ break;
989
+
990
+ case 'latest':
991
+ targetMessageSetIndex = this.messageSets.findIndex(function (s) {
992
+ return s.isLatest;
993
+ });
994
+ break;
995
+
996
+ default:
997
+ targetMessageSetIndex = -1;
998
+ } // when merging the target set will be the first one from the overlapping message sets
999
+
1000
+
1001
+ var mergeTargetMessageSetIndex = overlappingMessageSetIndices.splice(0, 1)[0];
1002
+
1003
+ var mergeSourceMessageSetIndices = _toConsumableArray__default['default'](overlappingMessageSetIndices);
1004
+
1005
+ if (mergeTargetMessageSetIndex !== undefined && mergeTargetMessageSetIndex !== targetMessageSetIndex) {
1006
+ mergeSourceMessageSetIndices.push(targetMessageSetIndex);
1007
+ } // merge message sets
1008
+
1009
+
1010
+ if (mergeSourceMessageSetIndices.length > 0) {
1011
+ var target = this.messageSets[mergeTargetMessageSetIndex];
1012
+ var sources = this.messageSets.filter(function (_, i) {
1013
+ return mergeSourceMessageSetIndices.indexOf(i) !== -1;
1014
+ });
1015
+ sources.forEach(function (messageSet) {
1016
+ target.isLatest = target.isLatest || messageSet.isLatest;
1017
+ target.isCurrent = target.isCurrent || messageSet.isCurrent;
1018
+ messagesToAdd = [].concat(_toConsumableArray__default['default'](messagesToAdd), _toConsumableArray__default['default'](messageSet.messages));
1019
+ });
1020
+ sources.forEach(function (s) {
1021
+ return _this5.messageSets.splice(_this5.messageSets.indexOf(s), 1);
1022
+ });
1023
+ var overlappingMessageSetIndex = this.messageSets.findIndex(function (s) {
1024
+ return _this5.areMessageSetsOverlap(s.messages, newMessages);
1025
+ });
1026
+ targetMessageSetIndex = overlappingMessageSetIndex;
1027
+ }
1028
+ } else {
1029
+ // assumes that all new messages belong to the same set
1030
+ targetMessageSetIndex = this.findMessageSetIndex(newMessages[0]);
1031
+ }
1032
+
1033
+ return {
1034
+ targetMessageSetIndex: targetMessageSetIndex,
1035
+ messagesToAdd: messagesToAdd
1036
+ };
1037
+ }
724
1038
  }]);
725
1039
 
726
1040
  return ChannelState;
@@ -1083,7 +1397,7 @@ var Channel = /*#__PURE__*/function () {
1083
1397
  presence: false
1084
1398
  };
1085
1399
  _context.next = 3;
1086
- return _this.query(options);
1400
+ return _this.query(options, 'latest');
1087
1401
 
1088
1402
  case 3:
1089
1403
  return _context.abrupt("return", _context.sent);
@@ -2381,14 +2695,14 @@ var Channel = /*#__PURE__*/function () {
2381
2695
  value: function lastMessage() {
2382
2696
  // get last 5 messages, sort, return the latest
2383
2697
  // get a slice of the last 5
2384
- var min = this.state.messages.length - 5;
2698
+ var min = this.state.latestMessages.length - 5;
2385
2699
 
2386
2700
  if (min < 0) {
2387
2701
  min = 0;
2388
2702
  }
2389
2703
 
2390
- var max = this.state.messages.length + 1;
2391
- var messageSlice = this.state.messages.slice(min, max); // sort by pk desc
2704
+ var max = this.state.latestMessages.length + 1;
2705
+ var messageSlice = this.state.latestMessages.slice(min, max); // sort by pk desc
2392
2706
 
2393
2707
  messageSlice.sort(function (a, b) {
2394
2708
  return b.created_at.getTime() - a.created_at.getTime();
@@ -2497,7 +2811,7 @@ var Channel = /*#__PURE__*/function () {
2497
2811
 
2498
2812
  combined = _objectSpread$5(_objectSpread$5({}, defaultOptions), options);
2499
2813
  _context27.next = 7;
2500
- return this.query(combined);
2814
+ return this.query(combined, 'latest');
2501
2815
 
2502
2816
  case 7:
2503
2817
  state = _context27.sent;
@@ -2571,7 +2885,7 @@ var Channel = /*#__PURE__*/function () {
2571
2885
  * getReplies - List the message replies for a parent message
2572
2886
  *
2573
2887
  * @param {string} parent_id The message parent id, ie the top of the thread
2574
- * @param {PaginationOptions & { user?: UserResponse<StreamChatGenerics>; user_id?: string }} options Pagination params, ie {limit:10, id_lte: 10}
2888
+ * @param {MessagePaginationOptions & { user?: UserResponse<StreamChatGenerics>; user_id?: string }} options Pagination params, ie {limit:10, id_lte: 10}
2575
2889
  *
2576
2890
  * @return {Promise<GetRepliesAPIResponse<StreamChatGenerics>>} A response with a list of messages
2577
2891
  */
@@ -2732,8 +3046,8 @@ var Channel = /*#__PURE__*/function () {
2732
3046
  if (!lastRead) return this.state.unreadCount;
2733
3047
  var count = 0;
2734
3048
 
2735
- for (var i = 0; i < this.state.messages.length; i += 1) {
2736
- var message = this.state.messages[i];
3049
+ for (var i = 0; i < this.state.latestMessages.length; i += 1) {
3050
+ var message = this.state.latestMessages[i];
2737
3051
 
2738
3052
  if (message.created_at > lastRead && this._countMessageAsUnread(message)) {
2739
3053
  count++;
@@ -2743,7 +3057,7 @@ var Channel = /*#__PURE__*/function () {
2743
3057
  return count;
2744
3058
  }
2745
3059
  /**
2746
- * countUnread - Count the number of unread messages mentioning the current user
3060
+ * countUnreadMentions - Count the number of unread messages mentioning the current user
2747
3061
  *
2748
3062
  * @return {number} Unread mentions count
2749
3063
  */
@@ -2755,10 +3069,10 @@ var Channel = /*#__PURE__*/function () {
2755
3069
  var userID = this.getClient().userID;
2756
3070
  var count = 0;
2757
3071
 
2758
- for (var i = 0; i < this.state.messages.length; i += 1) {
3072
+ for (var i = 0; i < this.state.latestMessages.length; i += 1) {
2759
3073
  var _message$mentioned_us;
2760
3074
 
2761
- var message = this.state.messages[i];
3075
+ var message = this.state.latestMessages[i];
2762
3076
 
2763
3077
  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) {
2764
3078
  return user.id === userID;
@@ -2782,33 +3096,40 @@ var Channel = /*#__PURE__*/function () {
2782
3096
  * query - Query the API, get messages, members or other channel fields
2783
3097
  *
2784
3098
  * @param {ChannelQueryOptions<StreamChatGenerics>} options The query options
3099
+ * @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
2785
3100
  *
2786
3101
  * @return {Promise<ChannelAPIResponse<StreamChatGenerics>>} Returns a query response
2787
3102
  */
2788
3103
  function () {
2789
3104
  var _query = _asyncToGenerator__default['default']( /*#__PURE__*/_regeneratorRuntime__default['default'].mark(function _callee31(options) {
2790
- var queryURL, state, membersStr, tempChannelCid;
3105
+ var messageSetToAddToIfDoesNotExist,
3106
+ queryURL,
3107
+ state,
3108
+ membersStr,
3109
+ tempChannelCid,
3110
+ _args31 = arguments;
2791
3111
  return _regeneratorRuntime__default['default'].wrap(function _callee31$(_context31) {
2792
3112
  while (1) {
2793
3113
  switch (_context31.prev = _context31.next) {
2794
3114
  case 0:
2795
- _context31.next = 2;
3115
+ messageSetToAddToIfDoesNotExist = _args31.length > 1 && _args31[1] !== undefined ? _args31[1] : 'current';
3116
+ _context31.next = 3;
2796
3117
  return this.getClient().wsPromise;
2797
3118
 
2798
- case 2:
3119
+ case 3:
2799
3120
  queryURL = "".concat(this.getClient().baseURL, "/channels/").concat(this.type);
2800
3121
 
2801
3122
  if (this.id) {
2802
3123
  queryURL += "/".concat(this.id);
2803
3124
  }
2804
3125
 
2805
- _context31.next = 6;
3126
+ _context31.next = 7;
2806
3127
  return this.getClient().post(queryURL + '/query', _objectSpread$5({
2807
3128
  data: this._data,
2808
3129
  state: true
2809
3130
  }, options));
2810
3131
 
2811
- case 6:
3132
+ case 7:
2812
3133
  state = _context31.sent;
2813
3134
 
2814
3135
  // update the channel id if it was missing
@@ -2837,11 +3158,11 @@ var Channel = /*#__PURE__*/function () {
2837
3158
  this.getClient()._addChannelConfig(state); // add any messages to our channel state
2838
3159
 
2839
3160
 
2840
- this._initializeState(state);
3161
+ this._initializeState(state, messageSetToAddToIfDoesNotExist);
2841
3162
 
2842
3163
  return _context31.abrupt("return", state);
2843
3164
 
2844
- case 11:
3165
+ case 12:
2845
3166
  case "end":
2846
3167
  return _context31.stop();
2847
3168
  }
@@ -3391,6 +3712,8 @@ var Channel = /*#__PURE__*/function () {
3391
3712
  }, {
3392
3713
  key: "_initializeState",
3393
3714
  value: function _initializeState(state) {
3715
+ var messageSetToAddToIfDoesNotExist = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'latest';
3716
+
3394
3717
  var _this$getClient2 = this.getClient(),
3395
3718
  clientState = _this$getClient2.state,
3396
3719
  user = _this$getClient2.user,
@@ -3420,10 +3743,10 @@ var Channel = /*#__PURE__*/function () {
3420
3743
  var messages = state.messages || [];
3421
3744
 
3422
3745
  if (!this.state.messages) {
3423
- this.state.messages = [];
3746
+ this.state.initMessages();
3424
3747
  }
3425
3748
 
3426
- this.state.addMessagesSorted(messages, false, true);
3749
+ this.state.addMessagesSorted(messages, false, true, true, messageSetToAddToIfDoesNotExist);
3427
3750
 
3428
3751
  if (!this.state.pinnedMessages) {
3429
3752
  this.state.pinnedMessages = [];
@@ -7461,11 +7784,11 @@ var StreamChat = /*#__PURE__*/function () {
7461
7784
  c.initialized = true;
7462
7785
 
7463
7786
  if (skipInitialization === undefined) {
7464
- c._initializeState(_channelState);
7787
+ c._initializeState(_channelState, 'latest');
7465
7788
  } else if (!skipInitialization.includes(_channelState.channel.id)) {
7466
7789
  c.state.clearMessages();
7467
7790
 
7468
- c._initializeState(_channelState);
7791
+ c._initializeState(_channelState, 'latest');
7469
7792
  }
7470
7793
 
7471
7794
  channels.push(c);
@@ -9200,7 +9523,7 @@ var StreamChat = /*#__PURE__*/function () {
9200
9523
  }, {
9201
9524
  key: "getUserAgent",
9202
9525
  value: function getUserAgent() {
9203
- return this.userAgent || "stream-chat-javascript-client-".concat(this.node ? 'node' : 'browser', "-", "6.2.0");
9526
+ return this.userAgent || "stream-chat-javascript-client-".concat(this.node ? 'node' : 'browser', "-", "6.3.0");
9204
9527
  }
9205
9528
  }, {
9206
9529
  key: "setUserAgent",
@@ -10370,6 +10693,122 @@ var StreamChat = /*#__PURE__*/function () {
10370
10693
 
10371
10694
  return _listImports;
10372
10695
  }()
10696
+ /**
10697
+ * upsertPushProvider - Create or Update a push provider
10698
+ *
10699
+ * Note: Works only for v2 push version is enabled on app settings.
10700
+ *
10701
+ * @param {PushProviderConfig} configuration of the provider you want to create or update
10702
+ *
10703
+ * @return {APIResponse & PushProviderUpsertResponse} A push provider
10704
+ */
10705
+
10706
+ }, {
10707
+ key: "upsertPushProvider",
10708
+ value: function () {
10709
+ var _upsertPushProvider = _asyncToGenerator__default['default']( /*#__PURE__*/_regeneratorRuntime__default['default'].mark(function _callee75(pushProvider) {
10710
+ return _regeneratorRuntime__default['default'].wrap(function _callee75$(_context75) {
10711
+ while (1) {
10712
+ switch (_context75.prev = _context75.next) {
10713
+ case 0:
10714
+ _context75.next = 2;
10715
+ return this.post(this.baseURL + "/push_providers", {
10716
+ push_provider: pushProvider
10717
+ });
10718
+
10719
+ case 2:
10720
+ return _context75.abrupt("return", _context75.sent);
10721
+
10722
+ case 3:
10723
+ case "end":
10724
+ return _context75.stop();
10725
+ }
10726
+ }
10727
+ }, _callee75, this);
10728
+ }));
10729
+
10730
+ function upsertPushProvider(_x98) {
10731
+ return _upsertPushProvider.apply(this, arguments);
10732
+ }
10733
+
10734
+ return upsertPushProvider;
10735
+ }()
10736
+ /**
10737
+ * deletePushProvider - Delete a push provider
10738
+ *
10739
+ * Note: Works only for v2 push version is enabled on app settings.
10740
+ *
10741
+ * @param {PushProviderID} type and foreign id of the push provider to be deleted
10742
+ *
10743
+ * @return {APIResponse} An API response
10744
+ */
10745
+
10746
+ }, {
10747
+ key: "deletePushProvider",
10748
+ value: function () {
10749
+ var _deletePushProvider = _asyncToGenerator__default['default']( /*#__PURE__*/_regeneratorRuntime__default['default'].mark(function _callee76(_ref8) {
10750
+ var type, name;
10751
+ return _regeneratorRuntime__default['default'].wrap(function _callee76$(_context76) {
10752
+ while (1) {
10753
+ switch (_context76.prev = _context76.next) {
10754
+ case 0:
10755
+ type = _ref8.type, name = _ref8.name;
10756
+ _context76.next = 3;
10757
+ return this.delete(this.baseURL + "/push_providers/".concat(type, "/").concat(name));
10758
+
10759
+ case 3:
10760
+ return _context76.abrupt("return", _context76.sent);
10761
+
10762
+ case 4:
10763
+ case "end":
10764
+ return _context76.stop();
10765
+ }
10766
+ }
10767
+ }, _callee76, this);
10768
+ }));
10769
+
10770
+ function deletePushProvider(_x99) {
10771
+ return _deletePushProvider.apply(this, arguments);
10772
+ }
10773
+
10774
+ return deletePushProvider;
10775
+ }()
10776
+ /**
10777
+ * listPushProviders - Get all push providers in the app
10778
+ *
10779
+ * Note: Works only for v2 push version is enabled on app settings.
10780
+ *
10781
+ * @return {APIResponse & PushProviderListResponse} A push provider
10782
+ */
10783
+
10784
+ }, {
10785
+ key: "listPushProviders",
10786
+ value: function () {
10787
+ var _listPushProviders = _asyncToGenerator__default['default']( /*#__PURE__*/_regeneratorRuntime__default['default'].mark(function _callee77() {
10788
+ return _regeneratorRuntime__default['default'].wrap(function _callee77$(_context77) {
10789
+ while (1) {
10790
+ switch (_context77.prev = _context77.next) {
10791
+ case 0:
10792
+ _context77.next = 2;
10793
+ return this.get(this.baseURL + "/push_providers");
10794
+
10795
+ case 2:
10796
+ return _context77.abrupt("return", _context77.sent);
10797
+
10798
+ case 3:
10799
+ case "end":
10800
+ return _context77.stop();
10801
+ }
10802
+ }
10803
+ }, _callee77, this);
10804
+ }));
10805
+
10806
+ function listPushProviders() {
10807
+ return _listPushProviders.apply(this, arguments);
10808
+ }
10809
+
10810
+ return listPushProviders;
10811
+ }()
10373
10812
  }], [{
10374
10813
  key: "getInstance",
10375
10814
  value: function getInstance(key, secretOrOptions, options) {