polfan-server-js-client 0.3.2 → 0.3.3

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.
@@ -719,19 +719,16 @@ var PromiseRegistry = /*#__PURE__*/function () {
719
719
  function TopicHistoryWindow_typeof(o) { "@babel/helpers - typeof"; return TopicHistoryWindow_typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, TopicHistoryWindow_typeof(o); }
720
720
  function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
721
721
  function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { TopicHistoryWindow_defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
722
- function TopicHistoryWindow_superPropGet(t, o, e, r) { var p = TopicHistoryWindow_get(TopicHistoryWindow_getPrototypeOf(1 & r ? t.prototype : t), o, e); return 2 & r && "function" == typeof p ? function (t) { return p.apply(e, t); } : p; }
723
- function TopicHistoryWindow_get() { return TopicHistoryWindow_get = "undefined" != typeof Reflect && Reflect.get ? Reflect.get.bind() : function (e, t, r) { var p = TopicHistoryWindow_superPropBase(e, t); if (p) { var n = Object.getOwnPropertyDescriptor(p, t); return n.get ? n.get.call(arguments.length < 3 ? e : r) : n.value; } }, TopicHistoryWindow_get.apply(null, arguments); }
724
- function TopicHistoryWindow_superPropBase(t, o) { for (; !{}.hasOwnProperty.call(t, o) && null !== (t = TopicHistoryWindow_getPrototypeOf(t));); return t; }
722
+ function _regenerator() { /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/babel/babel/blob/main/packages/babel-helpers/LICENSE */ var e, t, r = "function" == typeof Symbol ? Symbol : {}, n = r.iterator || "@@iterator", o = r.toStringTag || "@@toStringTag"; function i(r, n, o, i) { var c = n && n.prototype instanceof Generator ? n : Generator, u = Object.create(c.prototype); return _regeneratorDefine2(u, "_invoke", function (r, n, o) { var i, c, u, f = 0, p = o || [], y = !1, G = { p: 0, n: 0, v: e, a: d, f: d.bind(e, 4), d: function d(t, r) { return i = t, c = 0, u = e, G.n = r, a; } }; function d(r, n) { for (c = r, u = n, t = 0; !y && f && !o && t < p.length; t++) { var o, i = p[t], d = G.p, l = i[2]; r > 3 ? (o = l === n) && (u = i[(c = i[4]) ? 5 : (c = 3, 3)], i[4] = i[5] = e) : i[0] <= d && ((o = r < 2 && d < i[1]) ? (c = 0, G.v = n, G.n = i[1]) : d < l && (o = r < 3 || i[0] > n || n > l) && (i[4] = r, i[5] = n, G.n = l, c = 0)); } if (o || r > 1) return a; throw y = !0, n; } return function (o, p, l) { if (f > 1) throw TypeError("Generator is already running"); for (y && 1 === p && d(p, l), c = p, u = l; (t = c < 2 ? e : u) || !y;) { i || (c ? c < 3 ? (c > 1 && (G.n = -1), d(c, u)) : G.n = u : G.v = u); try { if (f = 2, i) { if (c || (o = "next"), t = i[o]) { if (!(t = t.call(i, u))) throw TypeError("iterator result is not an object"); if (!t.done) return t; u = t.value, c < 2 && (c = 0); } else 1 === c && (t = i["return"]) && t.call(i), c < 2 && (u = TypeError("The iterator does not provide a '" + o + "' method"), c = 1); i = e; } else if ((t = (y = G.n < 0) ? u : r.call(n, G)) !== a) break; } catch (t) { i = e, c = 1, u = t; } finally { f = 1; } } return { value: t, done: y }; }; }(r, o, i), !0), u; } var a = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} t = Object.getPrototypeOf; var c = [][n] ? t(t([][n]())) : (_regeneratorDefine2(t = {}, n, function () { return this; }), t), u = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(c); function f(e) { return Object.setPrototypeOf ? Object.setPrototypeOf(e, GeneratorFunctionPrototype) : (e.__proto__ = GeneratorFunctionPrototype, _regeneratorDefine2(e, o, "GeneratorFunction")), e.prototype = Object.create(u), e; } return GeneratorFunction.prototype = GeneratorFunctionPrototype, _regeneratorDefine2(u, "constructor", GeneratorFunctionPrototype), _regeneratorDefine2(GeneratorFunctionPrototype, "constructor", GeneratorFunction), GeneratorFunction.displayName = "GeneratorFunction", _regeneratorDefine2(GeneratorFunctionPrototype, o, "GeneratorFunction"), _regeneratorDefine2(u), _regeneratorDefine2(u, o, "Generator"), _regeneratorDefine2(u, n, function () { return this; }), _regeneratorDefine2(u, "toString", function () { return "[object Generator]"; }), (_regenerator = function _regenerator() { return { w: i, m: f }; })(); }
723
+ function _regeneratorDefine2(e, r, n, t) { var i = Object.defineProperty; try { i({}, "", {}); } catch (e) { i = 0; } _regeneratorDefine2 = function _regeneratorDefine(e, r, n, t) { function o(r, n) { _regeneratorDefine2(e, r, function (e) { return this._invoke(r, n, e); }); } r ? i ? i(e, r, { value: n, enumerable: !t, configurable: !t, writable: !t }) : e[r] = n : (o("next", 0), o("throw", 1), o("return", 2)); }, _regeneratorDefine2(e, r, n, t); }
724
+ function asyncGeneratorStep(n, t, e, r, o, a, c) { try { var i = n[a](c), u = i.value; } catch (n) { return void e(n); } i.done ? t(u) : Promise.resolve(u).then(r, o); }
725
+ function _asyncToGenerator(n) { return function () { var t = this, e = arguments; return new Promise(function (r, o) { var a = n.apply(t, e); function _next(n) { asyncGeneratorStep(a, r, o, _next, _throw, "next", n); } function _throw(n) { asyncGeneratorStep(a, r, o, _next, _throw, "throw", n); } _next(void 0); }); }; }
725
726
  function TopicHistoryWindow_toConsumableArray(r) { return TopicHistoryWindow_arrayWithoutHoles(r) || TopicHistoryWindow_iterableToArray(r) || TopicHistoryWindow_unsupportedIterableToArray(r) || TopicHistoryWindow_nonIterableSpread(); }
726
727
  function TopicHistoryWindow_nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
727
728
  function TopicHistoryWindow_unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return TopicHistoryWindow_arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? TopicHistoryWindow_arrayLikeToArray(r, a) : void 0; } }
728
729
  function TopicHistoryWindow_iterableToArray(r) { if ("undefined" != typeof Symbol && null != r[Symbol.iterator] || null != r["@@iterator"]) return Array.from(r); }
729
730
  function TopicHistoryWindow_arrayWithoutHoles(r) { if (Array.isArray(r)) return TopicHistoryWindow_arrayLikeToArray(r); }
730
731
  function TopicHistoryWindow_arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
731
- function _regenerator() { /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/babel/babel/blob/main/packages/babel-helpers/LICENSE */ var e, t, r = "function" == typeof Symbol ? Symbol : {}, n = r.iterator || "@@iterator", o = r.toStringTag || "@@toStringTag"; function i(r, n, o, i) { var c = n && n.prototype instanceof Generator ? n : Generator, u = Object.create(c.prototype); return _regeneratorDefine2(u, "_invoke", function (r, n, o) { var i, c, u, f = 0, p = o || [], y = !1, G = { p: 0, n: 0, v: e, a: d, f: d.bind(e, 4), d: function d(t, r) { return i = t, c = 0, u = e, G.n = r, a; } }; function d(r, n) { for (c = r, u = n, t = 0; !y && f && !o && t < p.length; t++) { var o, i = p[t], d = G.p, l = i[2]; r > 3 ? (o = l === n) && (u = i[(c = i[4]) ? 5 : (c = 3, 3)], i[4] = i[5] = e) : i[0] <= d && ((o = r < 2 && d < i[1]) ? (c = 0, G.v = n, G.n = i[1]) : d < l && (o = r < 3 || i[0] > n || n > l) && (i[4] = r, i[5] = n, G.n = l, c = 0)); } if (o || r > 1) return a; throw y = !0, n; } return function (o, p, l) { if (f > 1) throw TypeError("Generator is already running"); for (y && 1 === p && d(p, l), c = p, u = l; (t = c < 2 ? e : u) || !y;) { i || (c ? c < 3 ? (c > 1 && (G.n = -1), d(c, u)) : G.n = u : G.v = u); try { if (f = 2, i) { if (c || (o = "next"), t = i[o]) { if (!(t = t.call(i, u))) throw TypeError("iterator result is not an object"); if (!t.done) return t; u = t.value, c < 2 && (c = 0); } else 1 === c && (t = i["return"]) && t.call(i), c < 2 && (u = TypeError("The iterator does not provide a '" + o + "' method"), c = 1); i = e; } else if ((t = (y = G.n < 0) ? u : r.call(n, G)) !== a) break; } catch (t) { i = e, c = 1, u = t; } finally { f = 1; } } return { value: t, done: y }; }; }(r, o, i), !0), u; } var a = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} t = Object.getPrototypeOf; var c = [][n] ? t(t([][n]())) : (_regeneratorDefine2(t = {}, n, function () { return this; }), t), u = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(c); function f(e) { return Object.setPrototypeOf ? Object.setPrototypeOf(e, GeneratorFunctionPrototype) : (e.__proto__ = GeneratorFunctionPrototype, _regeneratorDefine2(e, o, "GeneratorFunction")), e.prototype = Object.create(u), e; } return GeneratorFunction.prototype = GeneratorFunctionPrototype, _regeneratorDefine2(u, "constructor", GeneratorFunctionPrototype), _regeneratorDefine2(GeneratorFunctionPrototype, "constructor", GeneratorFunction), GeneratorFunction.displayName = "GeneratorFunction", _regeneratorDefine2(GeneratorFunctionPrototype, o, "GeneratorFunction"), _regeneratorDefine2(u), _regeneratorDefine2(u, o, "Generator"), _regeneratorDefine2(u, n, function () { return this; }), _regeneratorDefine2(u, "toString", function () { return "[object Generator]"; }), (_regenerator = function _regenerator() { return { w: i, m: f }; })(); }
732
- function _regeneratorDefine2(e, r, n, t) { var i = Object.defineProperty; try { i({}, "", {}); } catch (e) { i = 0; } _regeneratorDefine2 = function _regeneratorDefine(e, r, n, t) { function o(r, n) { _regeneratorDefine2(e, r, function (e) { return this._invoke(r, n, e); }); } r ? i ? i(e, r, { value: n, enumerable: !t, configurable: !t, writable: !t }) : e[r] = n : (o("next", 0), o("throw", 1), o("return", 2)); }, _regeneratorDefine2(e, r, n, t); }
733
- function asyncGeneratorStep(n, t, e, r, o, a, c) { try { var i = n[a](c), u = i.value; } catch (n) { return void e(n); } i.done ? t(u) : Promise.resolve(u).then(r, o); }
734
- function _asyncToGenerator(n) { return function () { var t = this, e = arguments; return new Promise(function (r, o) { var a = n.apply(t, e); function _next(n) { asyncGeneratorStep(a, r, o, _next, _throw, "next", n); } function _throw(n) { asyncGeneratorStep(a, r, o, _next, _throw, "throw", n); } _next(void 0); }); }; }
735
732
  function TopicHistoryWindow_classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); }
736
733
  function TopicHistoryWindow_defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, TopicHistoryWindow_toPropertyKey(o.key), o); } }
737
734
  function TopicHistoryWindow_createClass(e, r, t) { return r && TopicHistoryWindow_defineProperties(e.prototype, r), t && TopicHistoryWindow_defineProperties(e, t), Object.defineProperty(e, "prototype", { writable: !1 }), e; }
@@ -739,6 +736,9 @@ function TopicHistoryWindow_callSuper(t, o, e) { return o = TopicHistoryWindow_g
739
736
  function TopicHistoryWindow_possibleConstructorReturn(t, e) { if (e && ("object" == TopicHistoryWindow_typeof(e) || "function" == typeof e)) return e; if (void 0 !== e) throw new TypeError("Derived constructors may only return object or undefined"); return TopicHistoryWindow_assertThisInitialized(t); }
740
737
  function TopicHistoryWindow_assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); return e; }
741
738
  function TopicHistoryWindow_isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (TopicHistoryWindow_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }
739
+ function TopicHistoryWindow_superPropGet(t, o, e, r) { var p = TopicHistoryWindow_get(TopicHistoryWindow_getPrototypeOf(1 & r ? t.prototype : t), o, e); return 2 & r && "function" == typeof p ? function (t) { return p.apply(e, t); } : p; }
740
+ function TopicHistoryWindow_get() { return TopicHistoryWindow_get = "undefined" != typeof Reflect && Reflect.get ? Reflect.get.bind() : function (e, t, r) { var p = TopicHistoryWindow_superPropBase(e, t); if (p) { var n = Object.getOwnPropertyDescriptor(p, t); return n.get ? n.get.call(arguments.length < 3 ? e : r) : n.value; } }, TopicHistoryWindow_get.apply(null, arguments); }
741
+ function TopicHistoryWindow_superPropBase(t, o) { for (; !{}.hasOwnProperty.call(t, o) && null !== (t = TopicHistoryWindow_getPrototypeOf(t));); return t; }
742
742
  function TopicHistoryWindow_getPrototypeOf(t) { return TopicHistoryWindow_getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, TopicHistoryWindow_getPrototypeOf(t); }
743
743
  function TopicHistoryWindow_inherits(t, e) { if ("function" != typeof e && null !== e) throw new TypeError("Super expression must either be null or a function"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, "prototype", { writable: !1 }), e && TopicHistoryWindow_setPrototypeOf(t, e); }
744
744
  function TopicHistoryWindow_setPrototypeOf(t, e) { return TopicHistoryWindow_setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, TopicHistoryWindow_setPrototypeOf(t, e); }
@@ -782,7 +782,8 @@ var TraversableRemoteCollection = /*#__PURE__*/function (_ObservableIndexedObj)
782
782
  retainRatio: 1,
783
783
  fetchLimit: 50,
784
784
  lastFetchCount: 0,
785
- oldestId: null
785
+ oldestId: null,
786
+ gaps: []
786
787
  });
787
788
  return _this;
788
789
  }
@@ -851,6 +852,23 @@ var TraversableRemoteCollection = /*#__PURE__*/function (_ObservableIndexedObj)
851
852
  get: function get() {
852
853
  return [WindowState.LATEST, WindowState.LIVE].includes(this.state);
853
854
  }
855
+
856
+ /**
857
+ * IDs of the items the window could not stitch to the ones loaded before
858
+ * them: there is a gap in front of each of them, i.e. the item right above
859
+ * it in the window is not its real predecessor and an unknown number of
860
+ * items in between was never fetched.
861
+ *
862
+ * Such a gap appears when the collection is resynchronised after a
863
+ * reconnect (see resyncToLatest) and more items than a single page arrived
864
+ * while the connection was down. The markers are kept in the window order
865
+ * and disappear together with the items they point at.
866
+ */
867
+ }, {
868
+ key: "gaps",
869
+ get: function get() {
870
+ return TopicHistoryWindow_toConsumableArray(this.internalState.gaps);
871
+ }
854
872
  }, {
855
873
  key: "hasOldest",
856
874
  get: function get() {
@@ -888,6 +906,7 @@ var TraversableRemoteCollection = /*#__PURE__*/function (_ObservableIndexedObj)
888
906
  return _context.f(4);
889
907
  case 5:
890
908
  this._items.deleteAll(); // Directly call deleteAll to prevent event emit.
909
+ this.internalState.gaps = []; // Whole content is replaced, old markers mean nothing.
891
910
  this.addItems(result, 'tail');
892
911
  this.internalState.current = WindowState.LATEST;
893
912
  this.emitChangeWithDiff(true, originalState);
@@ -901,46 +920,119 @@ var TraversableRemoteCollection = /*#__PURE__*/function (_ObservableIndexedObj)
901
920
  }
902
921
  return resetToLatest;
903
922
  }()
923
+ /**
924
+ * Refresh the window with the latest page, keeping the already loaded items
925
+ * instead of replacing them.
926
+ *
927
+ * This is the reconnect-friendly variant of resetToLatest: the items missed
928
+ * while the connection was down are pulled with a single request and merged
929
+ * on top of the loaded ones (items returned in both are deduplicated), so
930
+ * the context the application already had does not disappear. The window
931
+ * size limit is the only thing that pushes the oldest items out.
932
+ *
933
+ * An empty or partial page is not a reason to drop anything: it only means
934
+ * the collection has little (or nothing) left on the remote side, while the
935
+ * items loaded earlier are still valid. When the page is full and does not
936
+ * reach the loaded items, an unknown number of items in between was never
937
+ * fetched - both parts are still kept, and the seam between them is recorded
938
+ * in `gaps` so the application can show where the history is not continuous.
939
+ */
904
940
  }, {
905
- key: "fetchPrevious",
906
- value: function () {
907
- var _fetchPrevious = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee2() {
908
- var result, originalState, firstItem;
941
+ key: "resyncToLatest",
942
+ value: (function () {
943
+ var _resyncToLatest = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee2() {
944
+ var _this2 = this;
945
+ var result, originalState, loaded, fetchedIds, retained, isContinuous;
909
946
  return _regenerator().w(function (_context2) {
910
947
  while (1) switch (_context2.p = _context2.n) {
911
948
  case 0:
912
- if (!(this.internalState.ongoing || this.hasOldest)) {
949
+ if (!this.internalState.ongoing) {
913
950
  _context2.n = 1;
914
951
  break;
915
952
  }
916
953
  return _context2.a(2);
917
954
  case 1:
918
955
  originalState = this.state;
919
- this.internalState.ongoing = WindowState.PAST;
956
+ this.internalState.ongoing = WindowState.LATEST;
920
957
  _context2.p = 2;
921
958
  _context2.n = 3;
922
- return this.fetchItemsBefore();
959
+ return this.fetchLatestItems();
923
960
  case 3:
924
961
  result = _context2.v;
925
- this.internalState.lastFetchCount = result ? result.length : 0;
962
+ this.internalState.lastFetchCount = result.length;
926
963
  case 4:
927
964
  _context2.p = 4;
928
965
  this.internalState.ongoing = undefined;
929
966
  return _context2.f(4);
967
+ case 5:
968
+ loaded = this.items;
969
+ fetchedIds = new Set(result.map(function (item) {
970
+ return _this2.getId(item);
971
+ })); // Items present in the page are taken from it - the server copy is the
972
+ // up-to-date one.
973
+ retained = loaded.filter(function (item) {
974
+ return !fetchedIds.has(_this2.getId(item));
975
+ }); // Nothing can be missing in between when there is nothing to stitch,
976
+ // when the page is everything the remote side has (it is shorter than
977
+ // the requested limit), or when the page reaches the newest loaded item.
978
+ isContinuous = !retained.length || result.length < this.internalState.fetchLimit || fetchedIds.has(this.getId(loaded[loaded.length - 1]));
979
+ if (!isContinuous) {
980
+ this.markGapBefore(this.getId(result[0]));
981
+ }
982
+ this._items.deleteAll(); // Directly call deleteAll to prevent event emit.
983
+ this.addItems([].concat(TopicHistoryWindow_toConsumableArray(retained), TopicHistoryWindow_toConsumableArray(result)), 'tail');
984
+ this.internalState.current = WindowState.LATEST;
985
+ this.emitChangeWithDiff(true, originalState);
986
+ case 6:
987
+ return _context2.a(2);
988
+ }
989
+ }, _callee2, this, [[2,, 4, 5]]);
990
+ }));
991
+ function resyncToLatest() {
992
+ return _resyncToLatest.apply(this, arguments);
993
+ }
994
+ return resyncToLatest;
995
+ }())
996
+ }, {
997
+ key: "fetchPrevious",
998
+ value: function () {
999
+ var _fetchPrevious = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee3() {
1000
+ var result, originalState, firstItem;
1001
+ return _regenerator().w(function (_context3) {
1002
+ while (1) switch (_context3.p = _context3.n) {
1003
+ case 0:
1004
+ if (!(this.internalState.ongoing || this.hasOldest)) {
1005
+ _context3.n = 1;
1006
+ break;
1007
+ }
1008
+ return _context3.a(2);
1009
+ case 1:
1010
+ originalState = this.state;
1011
+ firstItem = this.getAt(0);
1012
+ this.internalState.ongoing = WindowState.PAST;
1013
+ _context3.p = 2;
1014
+ _context3.n = 3;
1015
+ return this.fetchItemsBefore();
1016
+ case 3:
1017
+ result = _context3.v;
1018
+ this.internalState.lastFetchCount = result ? result.length : 0;
1019
+ case 4:
1020
+ _context3.p = 4;
1021
+ this.internalState.ongoing = undefined;
1022
+ return _context3.f(4);
930
1023
  case 5:
931
1024
  if (result) {
932
- _context2.n = 6;
1025
+ _context3.n = 6;
933
1026
  break;
934
1027
  }
935
- return _context2.a(2, this.resetToLatest());
1028
+ return _context3.a(2, this.resetToLatest());
936
1029
  case 6:
937
1030
  if (result.length) {
938
- _context2.n = 8;
1031
+ _context3.n = 8;
939
1032
  break;
940
1033
  }
941
- firstItem = this.getAt(0);
942
1034
  this.internalState.oldestId = firstItem ? this.getId(firstItem) : null;
943
- _context2.n = 7;
1035
+ _context3.n = 7;
944
1036
  return this.refreshFetchedState();
945
1037
  case 7:
946
1038
  // LATEST state has priority over OLDEST
@@ -948,17 +1040,23 @@ var TraversableRemoteCollection = /*#__PURE__*/function (_ObservableIndexedObj)
948
1040
  this.internalState.current = WindowState.OLDEST;
949
1041
  }
950
1042
  this.emitChangeWithDiff(false, originalState);
951
- return _context2.a(2);
1043
+ return _context3.a(2);
952
1044
  case 8:
1045
+ if (firstItem) {
1046
+ // The fetch asked for the items right before the one that was first,
1047
+ // so whatever came back is its real predecessor: a gap marked in
1048
+ // front of it (it used to be the top of the window) is closed now.
1049
+ this.clearGapBefore(this.getId(firstItem));
1050
+ }
953
1051
  this.addItems(result, 'head');
954
- _context2.n = 9;
1052
+ _context3.n = 9;
955
1053
  return this.refreshFetchedState();
956
1054
  case 9:
957
1055
  this.emitChangeWithDiff(true, originalState);
958
1056
  case 10:
959
- return _context2.a(2);
1057
+ return _context3.a(2);
960
1058
  }
961
- }, _callee2, this, [[2,, 4, 5]]);
1059
+ }, _callee3, this, [[2,, 4, 5]]);
962
1060
  }));
963
1061
  function fetchPrevious() {
964
1062
  return _fetchPrevious.apply(this, arguments);
@@ -968,53 +1066,53 @@ var TraversableRemoteCollection = /*#__PURE__*/function (_ObservableIndexedObj)
968
1066
  }, {
969
1067
  key: "fetchNext",
970
1068
  value: function () {
971
- var _fetchNext = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee3() {
1069
+ var _fetchNext = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee4() {
972
1070
  var result, originalState;
973
- return _regenerator().w(function (_context3) {
974
- while (1) switch (_context3.p = _context3.n) {
1071
+ return _regenerator().w(function (_context4) {
1072
+ while (1) switch (_context4.p = _context4.n) {
975
1073
  case 0:
976
1074
  if (!(this.internalState.ongoing || this.hasLatest)) {
977
- _context3.n = 1;
1075
+ _context4.n = 1;
978
1076
  break;
979
1077
  }
980
- return _context3.a(2);
1078
+ return _context4.a(2);
981
1079
  case 1:
982
1080
  originalState = this.state;
983
1081
  this.internalState.ongoing = WindowState.PAST;
984
- _context3.p = 2;
985
- _context3.n = 3;
1082
+ _context4.p = 2;
1083
+ _context4.n = 3;
986
1084
  return this.fetchItemsAfter();
987
1085
  case 3:
988
- result = _context3.v;
1086
+ result = _context4.v;
989
1087
  this.internalState.lastFetchCount = result ? result.length : 0;
990
1088
  case 4:
991
- _context3.p = 4;
1089
+ _context4.p = 4;
992
1090
  this.internalState.ongoing = undefined;
993
- return _context3.f(4);
1091
+ return _context4.f(4);
994
1092
  case 5:
995
1093
  if (result) {
996
- _context3.n = 7;
1094
+ _context4.n = 7;
997
1095
  break;
998
1096
  }
999
- _context3.n = 6;
1097
+ _context4.n = 6;
1000
1098
  return this.resetToLatest();
1001
1099
  case 6:
1002
- return _context3.a(2);
1100
+ return _context4.a(2);
1003
1101
  case 7:
1004
1102
  if (!result.length) {
1005
- _context3.n = 9;
1103
+ _context4.n = 9;
1006
1104
  break;
1007
1105
  }
1008
1106
  this.addItems(result, 'tail');
1009
- _context3.n = 8;
1107
+ _context4.n = 8;
1010
1108
  return this.refreshFetchedState();
1011
1109
  case 8:
1012
1110
  this.emitChangeWithDiff(true, originalState);
1013
- return _context3.a(2);
1111
+ return _context4.a(2);
1014
1112
  case 9:
1015
- return _context3.a(2);
1113
+ return _context4.a(2);
1016
1114
  }
1017
- }, _callee3, this, [[2,, 4, 5]]);
1115
+ }, _callee4, this, [[2,, 4, 5]]);
1018
1116
  }));
1019
1117
  function fetchNext() {
1020
1118
  return _fetchNext.apply(this, arguments);
@@ -1024,75 +1122,91 @@ var TraversableRemoteCollection = /*#__PURE__*/function (_ObservableIndexedObj)
1024
1122
  }, {
1025
1123
  key: "jumpTo",
1026
1124
  value: function () {
1027
- var _jumpTo = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee4(id) {
1125
+ var _jumpTo = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee5(id) {
1028
1126
  var result, originalState;
1029
- return _regenerator().w(function (_context4) {
1030
- while (1) switch (_context4.p = _context4.n) {
1127
+ return _regenerator().w(function (_context5) {
1128
+ while (1) switch (_context5.p = _context5.n) {
1031
1129
  case 0:
1032
1130
  if (!(this.internalState.ongoing || this.state !== WindowState.LIVE && this._items.has(id))) {
1033
- _context4.n = 1;
1131
+ _context5.n = 1;
1034
1132
  break;
1035
1133
  }
1036
- return _context4.a(2);
1134
+ return _context5.a(2);
1037
1135
  case 1:
1038
1136
  originalState = this.state;
1039
1137
  this.internalState.ongoing = WindowState.PAST;
1040
- _context4.p = 2;
1041
- _context4.n = 3;
1138
+ _context5.p = 2;
1139
+ _context5.n = 3;
1042
1140
  return this.fetchItemsAround(id);
1043
1141
  case 3:
1044
- result = _context4.v;
1142
+ result = _context5.v;
1045
1143
  this.internalState.lastFetchCount = result ? result.length : 0;
1046
1144
  if (!result) {
1047
- _context4.n = 4;
1145
+ _context5.n = 4;
1048
1146
  break;
1049
1147
  }
1050
1148
  this._items.deleteAll(); // Directly call deleteAll to prevent event emit.
1149
+ this.internalState.gaps = []; // Whole content is replaced, old markers mean nothing.
1051
1150
  this.addItems(result, 'tail');
1052
- _context4.n = 4;
1151
+ _context5.n = 4;
1053
1152
  return this.refreshFetchedState();
1054
1153
  case 4:
1055
- _context4.p = 4;
1154
+ _context5.p = 4;
1056
1155
  this.internalState.ongoing = undefined;
1057
- return _context4.f(4);
1156
+ return _context5.f(4);
1058
1157
  case 5:
1059
1158
  this.emitChangeWithDiff(!!result, originalState);
1060
1159
  case 6:
1061
- return _context4.a(2);
1160
+ return _context5.a(2);
1062
1161
  }
1063
- }, _callee4, this, [[2,, 4, 5]]);
1162
+ }, _callee5, this, [[2,, 4, 5]]);
1064
1163
  }));
1065
1164
  function jumpTo(_x) {
1066
1165
  return _jumpTo.apply(this, arguments);
1067
1166
  }
1068
1167
  return jumpTo;
1069
1168
  }()
1169
+ }, {
1170
+ key: "delete",
1171
+ value: function _delete() {
1172
+ for (var _len2 = arguments.length, ids = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
1173
+ ids[_key2] = arguments[_key2];
1174
+ }
1175
+ TopicHistoryWindow_superPropGet(TraversableRemoteCollection, "delete", this, 3)(ids);
1176
+ this.dropDanglingGaps();
1177
+ }
1178
+ }, {
1179
+ key: "deleteAll",
1180
+ value: function deleteAll() {
1181
+ TopicHistoryWindow_superPropGet(TraversableRemoteCollection, "deleteAll", this, 3)([]);
1182
+ this.internalState.gaps = [];
1183
+ }
1070
1184
  }, {
1071
1185
  key: "refreshFetchedState",
1072
1186
  value: function () {
1073
- var _refreshFetchedState = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee5() {
1187
+ var _refreshFetchedState = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee6() {
1074
1188
  var _t;
1075
- return _regenerator().w(function (_context5) {
1076
- while (1) switch (_context5.n) {
1189
+ return _regenerator().w(function (_context6) {
1190
+ while (1) switch (_context6.n) {
1077
1191
  case 0:
1078
- _context5.n = 1;
1192
+ _context6.n = 1;
1079
1193
  return this.isLatestItemLoaded();
1080
1194
  case 1:
1081
- if (!_context5.v) {
1082
- _context5.n = 2;
1195
+ if (!_context6.v) {
1196
+ _context6.n = 2;
1083
1197
  break;
1084
1198
  }
1085
1199
  _t = WindowState.LATEST;
1086
- _context5.n = 3;
1200
+ _context6.n = 3;
1087
1201
  break;
1088
1202
  case 2:
1089
1203
  _t = WindowState.PAST;
1090
1204
  case 3:
1091
1205
  this.internalState.current = _t;
1092
1206
  case 4:
1093
- return _context5.a(2);
1207
+ return _context6.a(2);
1094
1208
  }
1095
- }, _callee5, this);
1209
+ }, _callee6, this);
1096
1210
  }));
1097
1211
  function refreshFetchedState() {
1098
1212
  return _refreshFetchedState.apply(this, arguments);
@@ -1103,7 +1217,7 @@ var TraversableRemoteCollection = /*#__PURE__*/function (_ObservableIndexedObj)
1103
1217
  key: "addItems",
1104
1218
  value: function addItems(newItems, to) {
1105
1219
  var _this$_items,
1106
- _this2 = this;
1220
+ _this3 = this;
1107
1221
  var result;
1108
1222
  if (to === 'head') {
1109
1223
  result = this.trimItemsArrayToLimit([].concat(TopicHistoryWindow_toConsumableArray(newItems), TopicHistoryWindow_toConsumableArray(this.items)), 'tail');
@@ -1115,8 +1229,9 @@ var TraversableRemoteCollection = /*#__PURE__*/function (_ObservableIndexedObj)
1115
1229
  // Directly calls to prevent event emit.
1116
1230
  this._items.deleteAll();
1117
1231
  (_this$_items = this._items).set.apply(_this$_items, TopicHistoryWindow_toConsumableArray(result.map(function (item) {
1118
- return [_this2.getId(item), item];
1232
+ return [_this3.getId(item), item];
1119
1233
  })));
1234
+ this.dropDanglingGaps();
1120
1235
  }
1121
1236
  }, {
1122
1237
  key: "emitChangeWithDiff",
@@ -1128,6 +1243,47 @@ var TraversableRemoteCollection = /*#__PURE__*/function (_ObservableIndexedObj)
1128
1243
  }
1129
1244
  }
1130
1245
 
1246
+ /**
1247
+ * Record that the history is not continuous in front of the given item.
1248
+ */
1249
+ }, {
1250
+ key: "markGapBefore",
1251
+ value: function markGapBefore(id) {
1252
+ if (!this.internalState.gaps.includes(id)) {
1253
+ this.internalState.gaps = [].concat(TopicHistoryWindow_toConsumableArray(this.internalState.gaps), [id]);
1254
+ }
1255
+ }
1256
+
1257
+ /**
1258
+ * Forget the gap in front of the given item - the items before it are known
1259
+ * to be its real predecessors now.
1260
+ */
1261
+ }, {
1262
+ key: "clearGapBefore",
1263
+ value: function clearGapBefore(id) {
1264
+ if (this.internalState.gaps.includes(id)) {
1265
+ this.internalState.gaps = this.internalState.gaps.filter(function (gapId) {
1266
+ return gapId !== id;
1267
+ });
1268
+ }
1269
+ }
1270
+
1271
+ /**
1272
+ * Forget the gap markers pointing at items that are no longer in the window
1273
+ * (trimmed, deleted or replaced), so `gaps` never refers to nothing.
1274
+ */
1275
+ }, {
1276
+ key: "dropDanglingGaps",
1277
+ value: function dropDanglingGaps() {
1278
+ var _this4 = this;
1279
+ if (!this.internalState.gaps.length) {
1280
+ return;
1281
+ }
1282
+ this.internalState.gaps = this.internalState.gaps.filter(function (id) {
1283
+ return _this4.has(id);
1284
+ });
1285
+ }
1286
+
1131
1287
  /**
1132
1288
  * Return array with messages trimmed using High/Low Watermark strategy.
1133
1289
  */
@@ -1151,27 +1307,27 @@ var TraversableRemoteCollection = /*#__PURE__*/function (_ObservableIndexedObj)
1151
1307
  }(ObservableIndexedObjectCollection);
1152
1308
  var TopicHistoryWindow = /*#__PURE__*/function (_TraversableRemoteCol) {
1153
1309
  function TopicHistoryWindow(roomId, topicId, tracker) {
1154
- var _this3;
1310
+ var _this5;
1155
1311
  var bindEvents = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : true;
1156
1312
  TopicHistoryWindow_classCallCheck(this, TopicHistoryWindow);
1157
- _this3 = TopicHistoryWindow_callSuper(this, TopicHistoryWindow, ['id']);
1313
+ _this5 = TopicHistoryWindow_callSuper(this, TopicHistoryWindow, ['id']);
1158
1314
  /**
1159
1315
  * Reexported available window modes enum.
1160
1316
  */
1161
- TopicHistoryWindow_defineProperty(_this3, "WindowState", WindowState);
1162
- _this3.roomId = roomId;
1163
- _this3.topicId = topicId;
1164
- _this3.tracker = tracker;
1165
- _this3.internalState.traverseLock = false;
1317
+ TopicHistoryWindow_defineProperty(_this5, "WindowState", WindowState);
1318
+ _this5.roomId = roomId;
1319
+ _this5.topicId = topicId;
1320
+ _this5.tracker = tracker;
1321
+ _this5.internalState.traverseLock = false;
1166
1322
  if (bindEvents) {
1167
- _this3.tracker.client.on('NewMessage', function (ev) {
1168
- return _this3.handleNewMessage(ev);
1323
+ _this5.tracker.client.on('NewMessage', function (ev) {
1324
+ return _this5.handleNewMessage(ev);
1169
1325
  });
1170
- _this3.tracker.client.on('MessagesRedacted', function (ev) {
1171
- return _this3.handleMessagesRedacted(ev);
1326
+ _this5.tracker.client.on('MessagesRedacted', function (ev) {
1327
+ return _this5.handleMessagesRedacted(ev);
1172
1328
  });
1173
1329
  }
1174
- return _this3;
1330
+ return _this5;
1175
1331
  }
1176
1332
  TopicHistoryWindow_inherits(TopicHistoryWindow, _TraversableRemoteCol);
1177
1333
  return TopicHistoryWindow_createClass(TopicHistoryWindow, [{
@@ -1191,21 +1347,21 @@ var TopicHistoryWindow = /*#__PURE__*/function (_TraversableRemoteCol) {
1191
1347
  }, {
1192
1348
  key: "setTraverseLock",
1193
1349
  value: function () {
1194
- var _setTraverseLock = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee6(lock) {
1195
- return _regenerator().w(function (_context6) {
1196
- while (1) switch (_context6.n) {
1350
+ var _setTraverseLock = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee7(lock) {
1351
+ return _regenerator().w(function (_context7) {
1352
+ while (1) switch (_context7.n) {
1197
1353
  case 0:
1198
1354
  this.internalState.traverseLock = lock;
1199
1355
  if (!(lock && this.state !== WindowState.LIVE && this.state !== WindowState.LATEST)) {
1200
- _context6.n = 1;
1356
+ _context7.n = 1;
1201
1357
  break;
1202
1358
  }
1203
- _context6.n = 1;
1359
+ _context7.n = 1;
1204
1360
  return TopicHistoryWindow_superPropGet(TopicHistoryWindow, "resetToLatest", this, 3)([]);
1205
1361
  case 1:
1206
- return _context6.a(2);
1362
+ return _context7.a(2);
1207
1363
  }
1208
- }, _callee6, this);
1364
+ }, _callee7, this);
1209
1365
  }));
1210
1366
  function setTraverseLock(_x2) {
1211
1367
  return _setTraverseLock.apply(this, arguments);
@@ -1215,44 +1371,66 @@ var TopicHistoryWindow = /*#__PURE__*/function (_TraversableRemoteCol) {
1215
1371
  }, {
1216
1372
  key: "resetToLatest",
1217
1373
  value: function () {
1218
- var _resetToLatest2 = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee7() {
1374
+ var _resetToLatest2 = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee8() {
1219
1375
  var force,
1220
- _args7 = arguments;
1221
- return _regenerator().w(function (_context7) {
1222
- while (1) switch (_context7.n) {
1376
+ _args8 = arguments;
1377
+ return _regenerator().w(function (_context8) {
1378
+ while (1) switch (_context8.n) {
1223
1379
  case 0:
1224
- force = _args7.length > 0 && _args7[0] !== undefined ? _args7[0] : false;
1380
+ force = _args8.length > 0 && _args8[0] !== undefined ? _args8[0] : false;
1225
1381
  if (!this.internalState.traverseLock) {
1226
- _context7.n = 1;
1382
+ _context8.n = 1;
1227
1383
  break;
1228
1384
  }
1229
- return _context7.a(2);
1385
+ return _context8.a(2);
1230
1386
  case 1:
1231
- return _context7.a(2, TopicHistoryWindow_superPropGet(TopicHistoryWindow, "resetToLatest", this, 3)([force]));
1387
+ return _context8.a(2, TopicHistoryWindow_superPropGet(TopicHistoryWindow, "resetToLatest", this, 3)([force]));
1232
1388
  }
1233
- }, _callee7, this);
1389
+ }, _callee8, this);
1234
1390
  }));
1235
1391
  function resetToLatest() {
1236
1392
  return _resetToLatest2.apply(this, arguments);
1237
1393
  }
1238
1394
  return resetToLatest;
1239
1395
  }()
1396
+ }, {
1397
+ key: "resyncToLatest",
1398
+ value: function () {
1399
+ var _resyncToLatest2 = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee9() {
1400
+ return _regenerator().w(function (_context9) {
1401
+ while (1) switch (_context9.n) {
1402
+ case 0:
1403
+ if (!this.internalState.traverseLock) {
1404
+ _context9.n = 1;
1405
+ break;
1406
+ }
1407
+ return _context9.a(2);
1408
+ case 1:
1409
+ return _context9.a(2, TopicHistoryWindow_superPropGet(TopicHistoryWindow, "resyncToLatest", this, 3)([]));
1410
+ }
1411
+ }, _callee9, this);
1412
+ }));
1413
+ function resyncToLatest() {
1414
+ return _resyncToLatest2.apply(this, arguments);
1415
+ }
1416
+ return resyncToLatest;
1417
+ }()
1240
1418
  }, {
1241
1419
  key: "fetchNext",
1242
1420
  value: function () {
1243
- var _fetchNext2 = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee8() {
1244
- return _regenerator().w(function (_context8) {
1245
- while (1) switch (_context8.n) {
1421
+ var _fetchNext2 = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee0() {
1422
+ return _regenerator().w(function (_context0) {
1423
+ while (1) switch (_context0.n) {
1246
1424
  case 0:
1247
1425
  if (!this.internalState.traverseLock) {
1248
- _context8.n = 1;
1426
+ _context0.n = 1;
1249
1427
  break;
1250
1428
  }
1251
- return _context8.a(2);
1429
+ return _context0.a(2);
1252
1430
  case 1:
1253
- return _context8.a(2, TopicHistoryWindow_superPropGet(TopicHistoryWindow, "fetchNext", this, 3)([]));
1431
+ return _context0.a(2, TopicHistoryWindow_superPropGet(TopicHistoryWindow, "fetchNext", this, 3)([]));
1254
1432
  }
1255
- }, _callee8, this);
1433
+ }, _callee0, this);
1256
1434
  }));
1257
1435
  function fetchNext() {
1258
1436
  return _fetchNext2.apply(this, arguments);
@@ -1262,19 +1440,19 @@ var TopicHistoryWindow = /*#__PURE__*/function (_TraversableRemoteCol) {
1262
1440
  }, {
1263
1441
  key: "fetchPrevious",
1264
1442
  value: function () {
1265
- var _fetchPrevious2 = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee9() {
1266
- return _regenerator().w(function (_context9) {
1267
- while (1) switch (_context9.n) {
1443
+ var _fetchPrevious2 = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee1() {
1444
+ return _regenerator().w(function (_context1) {
1445
+ while (1) switch (_context1.n) {
1268
1446
  case 0:
1269
1447
  if (!this.internalState.traverseLock) {
1270
- _context9.n = 1;
1448
+ _context1.n = 1;
1271
1449
  break;
1272
1450
  }
1273
- return _context9.a(2);
1451
+ return _context1.a(2);
1274
1452
  case 1:
1275
- return _context9.a(2, TopicHistoryWindow_superPropGet(TopicHistoryWindow, "fetchPrevious", this, 3)([]));
1453
+ return _context1.a(2, TopicHistoryWindow_superPropGet(TopicHistoryWindow, "fetchPrevious", this, 3)([]));
1276
1454
  }
1277
- }, _callee9, this);
1455
+ }, _callee1, this);
1278
1456
  }));
1279
1457
  function fetchPrevious() {
1280
1458
  return _fetchPrevious2.apply(this, arguments);
@@ -1284,19 +1462,19 @@ var TopicHistoryWindow = /*#__PURE__*/function (_TraversableRemoteCol) {
1284
1462
  }, {
1285
1463
  key: "jumpTo",
1286
1464
  value: function () {
1287
- var _jumpTo2 = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee0(id) {
1288
- return _regenerator().w(function (_context0) {
1289
- while (1) switch (_context0.n) {
1465
+ var _jumpTo2 = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee10(id) {
1466
+ return _regenerator().w(function (_context10) {
1467
+ while (1) switch (_context10.n) {
1290
1468
  case 0:
1291
1469
  if (!this.internalState.traverseLock) {
1292
- _context0.n = 1;
1470
+ _context10.n = 1;
1293
1471
  break;
1294
1472
  }
1295
- return _context0.a(2);
1473
+ return _context10.a(2);
1296
1474
  case 1:
1297
- return _context0.a(2, TopicHistoryWindow_superPropGet(TopicHistoryWindow, "jumpTo", this, 3)([id]));
1475
+ return _context10.a(2, TopicHistoryWindow_superPropGet(TopicHistoryWindow, "jumpTo", this, 3)([id]));
1298
1476
  }
1299
- }, _callee0, this);
1477
+ }, _callee10, this);
1300
1478
  }));
1301
1479
  function jumpTo(_x3) {
1302
1480
  return _jumpTo2.apply(this, arguments);
@@ -1321,20 +1499,20 @@ var TopicHistoryWindow = /*#__PURE__*/function (_TraversableRemoteCol) {
1321
1499
  }, {
1322
1500
  key: "fetchItemsAfter",
1323
1501
  value: function () {
1324
- var _fetchItemsAfter = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee1() {
1502
+ var _fetchItemsAfter = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee11() {
1325
1503
  var _this$getAt;
1326
1504
  var afterId, result;
1327
- return _regenerator().w(function (_context1) {
1328
- while (1) switch (_context1.n) {
1505
+ return _regenerator().w(function (_context11) {
1506
+ while (1) switch (_context11.n) {
1329
1507
  case 0:
1330
1508
  afterId = (_this$getAt = this.getAt(this.length - 1)) === null || _this$getAt === void 0 ? void 0 : _this$getAt.id;
1331
1509
  if (afterId) {
1332
- _context1.n = 1;
1510
+ _context11.n = 1;
1333
1511
  break;
1334
1512
  }
1335
- return _context1.a(2, null);
1513
+ return _context11.a(2, null);
1336
1514
  case 1:
1337
- _context1.n = 2;
1515
+ _context11.n = 2;
1338
1516
  return this.tracker.client.send('GetMessages', {
1339
1517
  location: {
1340
1518
  roomId: this.roomId,
@@ -1344,16 +1522,16 @@ var TopicHistoryWindow = /*#__PURE__*/function (_TraversableRemoteCol) {
1344
1522
  limit: this.internalState.fetchLimit
1345
1523
  });
1346
1524
  case 2:
1347
- result = _context1.v;
1525
+ result = _context11.v;
1348
1526
  if (!result.error) {
1349
- _context1.n = 3;
1527
+ _context11.n = 3;
1350
1528
  break;
1351
1529
  }
1352
1530
  throw new Error("Cannot fetch messages: ".concat(result.error.message));
1353
1531
  case 3:
1354
- return _context1.a(2, result.data.messages);
1532
+ return _context11.a(2, result.data.messages);
1355
1533
  }
1356
- }, _callee1, this);
1534
+ }, _callee11, this);
1357
1535
  }));
1358
1536
  function fetchItemsAfter() {
1359
1537
  return _fetchItemsAfter.apply(this, arguments);
@@ -1363,12 +1541,12 @@ var TopicHistoryWindow = /*#__PURE__*/function (_TraversableRemoteCol) {
1363
1541
  }, {
1364
1542
  key: "fetchItemsAround",
1365
1543
  value: function () {
1366
- var _fetchItemsAround = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee10(id) {
1544
+ var _fetchItemsAround = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee12(id) {
1367
1545
  var result;
1368
- return _regenerator().w(function (_context10) {
1369
- while (1) switch (_context10.n) {
1546
+ return _regenerator().w(function (_context12) {
1547
+ while (1) switch (_context12.n) {
1370
1548
  case 0:
1371
- _context10.n = 1;
1549
+ _context12.n = 1;
1372
1550
  return this.tracker.client.send('GetMessages', {
1373
1551
  location: {
1374
1552
  roomId: this.roomId,
@@ -1378,16 +1556,16 @@ var TopicHistoryWindow = /*#__PURE__*/function (_TraversableRemoteCol) {
1378
1556
  limit: this.internalState.fetchLimit
1379
1557
  });
1380
1558
  case 1:
1381
- result = _context10.v;
1559
+ result = _context12.v;
1382
1560
  if (!result.error) {
1383
- _context10.n = 2;
1561
+ _context12.n = 2;
1384
1562
  break;
1385
1563
  }
1386
1564
  throw new Error("Cannot fetch messages: ".concat(result.error.message));
1387
1565
  case 2:
1388
- return _context10.a(2, result.data.messages);
1566
+ return _context12.a(2, result.data.messages);
1389
1567
  }
1390
- }, _callee10, this);
1568
+ }, _callee12, this);
1391
1569
  }));
1392
1570
  function fetchItemsAround(_x4) {
1393
1571
  return _fetchItemsAround.apply(this, arguments);
@@ -1397,20 +1575,20 @@ var TopicHistoryWindow = /*#__PURE__*/function (_TraversableRemoteCol) {
1397
1575
  }, {
1398
1576
  key: "fetchItemsBefore",
1399
1577
  value: function () {
1400
- var _fetchItemsBefore = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee11() {
1578
+ var _fetchItemsBefore = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee13() {
1401
1579
  var _this$getAt2;
1402
1580
  var beforeId, result;
1403
- return _regenerator().w(function (_context11) {
1404
- while (1) switch (_context11.n) {
1581
+ return _regenerator().w(function (_context13) {
1582
+ while (1) switch (_context13.n) {
1405
1583
  case 0:
1406
1584
  beforeId = (_this$getAt2 = this.getAt(0)) === null || _this$getAt2 === void 0 ? void 0 : _this$getAt2.id;
1407
1585
  if (beforeId) {
1408
- _context11.n = 1;
1586
+ _context13.n = 1;
1409
1587
  break;
1410
1588
  }
1411
- return _context11.a(2, null);
1589
+ return _context13.a(2, null);
1412
1590
  case 1:
1413
- _context11.n = 2;
1591
+ _context13.n = 2;
1414
1592
  return this.tracker.client.send('GetMessages', {
1415
1593
  location: {
1416
1594
  roomId: this.roomId,
@@ -1420,16 +1598,16 @@ var TopicHistoryWindow = /*#__PURE__*/function (_TraversableRemoteCol) {
1420
1598
  limit: this.internalState.fetchLimit
1421
1599
  });
1422
1600
  case 2:
1423
- result = _context11.v;
1601
+ result = _context13.v;
1424
1602
  if (!result.error) {
1425
- _context11.n = 3;
1603
+ _context13.n = 3;
1426
1604
  break;
1427
1605
  }
1428
1606
  throw new Error("Cannot fetch messages: ".concat(result.error.message));
1429
1607
  case 3:
1430
- return _context11.a(2, result.data.messages);
1608
+ return _context13.a(2, result.data.messages);
1431
1609
  }
1432
- }, _callee11, this);
1610
+ }, _callee13, this);
1433
1611
  }));
1434
1612
  function fetchItemsBefore() {
1435
1613
  return _fetchItemsBefore.apply(this, arguments);
@@ -1439,12 +1617,12 @@ var TopicHistoryWindow = /*#__PURE__*/function (_TraversableRemoteCol) {
1439
1617
  }, {
1440
1618
  key: "fetchLatestItems",
1441
1619
  value: function () {
1442
- var _fetchLatestItems = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee12() {
1620
+ var _fetchLatestItems = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee14() {
1443
1621
  var result;
1444
- return _regenerator().w(function (_context12) {
1445
- while (1) switch (_context12.n) {
1622
+ return _regenerator().w(function (_context14) {
1623
+ while (1) switch (_context14.n) {
1446
1624
  case 0:
1447
- _context12.n = 1;
1625
+ _context14.n = 1;
1448
1626
  return this.tracker.client.send('GetMessages', {
1449
1627
  location: {
1450
1628
  roomId: this.roomId,
@@ -1453,16 +1631,16 @@ var TopicHistoryWindow = /*#__PURE__*/function (_TraversableRemoteCol) {
1453
1631
  limit: this.internalState.fetchLimit
1454
1632
  });
1455
1633
  case 1:
1456
- result = _context12.v;
1634
+ result = _context14.v;
1457
1635
  if (!result.error) {
1458
- _context12.n = 2;
1636
+ _context14.n = 2;
1459
1637
  break;
1460
1638
  }
1461
1639
  throw new Error("Cannot fetch messages: ".concat(result.error.message));
1462
1640
  case 2:
1463
- return _context12.a(2, result.data.messages);
1641
+ return _context14.a(2, result.data.messages);
1464
1642
  }
1465
- }, _callee12, this);
1643
+ }, _callee14, this);
1466
1644
  }));
1467
1645
  function fetchLatestItems() {
1468
1646
  return _fetchLatestItems.apply(this, arguments);
@@ -1472,16 +1650,16 @@ var TopicHistoryWindow = /*#__PURE__*/function (_TraversableRemoteCol) {
1472
1650
  }, {
1473
1651
  key: "getTopic",
1474
1652
  value: function () {
1475
- var _getTopic = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee13() {
1476
- return _regenerator().w(function (_context13) {
1477
- while (1) switch (_context13.n) {
1653
+ var _getTopic = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee15() {
1654
+ return _regenerator().w(function (_context15) {
1655
+ while (1) switch (_context15.n) {
1478
1656
  case 0:
1479
- _context13.n = 1;
1657
+ _context15.n = 1;
1480
1658
  return this.tracker.rooms.getTopics(this.roomId, [this.topicId]);
1481
1659
  case 1:
1482
- return _context13.a(2, _context13.v.get(this.topicId));
1660
+ return _context15.a(2, _context15.v.get(this.topicId));
1483
1661
  }
1484
- }, _callee13, this);
1662
+ }, _callee15, this);
1485
1663
  }));
1486
1664
  function getTopic() {
1487
1665
  return _getTopic.apply(this, arguments);
@@ -1491,43 +1669,43 @@ var TopicHistoryWindow = /*#__PURE__*/function (_TraversableRemoteCol) {
1491
1669
  }, {
1492
1670
  key: "getLatestMessageId",
1493
1671
  value: function () {
1494
- var _getLatestMessageId = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee14() {
1672
+ var _getLatestMessageId = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee16() {
1495
1673
  var _yield$this$getTopic;
1496
1674
  var _t2, _t3, _t4, _t5;
1497
- return _regenerator().w(function (_context14) {
1498
- while (1) switch (_context14.n) {
1675
+ return _regenerator().w(function (_context16) {
1676
+ while (1) switch (_context16.n) {
1499
1677
  case 0:
1500
- _context14.n = 1;
1678
+ _context16.n = 1;
1501
1679
  return this.getTopic();
1502
1680
  case 1:
1503
- _t4 = _yield$this$getTopic = _context14.v;
1681
+ _t4 = _yield$this$getTopic = _context16.v;
1504
1682
  _t3 = _t4 === null;
1505
1683
  if (_t3) {
1506
- _context14.n = 2;
1684
+ _context16.n = 2;
1507
1685
  break;
1508
1686
  }
1509
1687
  _t3 = _yield$this$getTopic === void 0;
1510
1688
  case 2:
1511
1689
  _t2 = _t3;
1512
1690
  if (_t2) {
1513
- _context14.n = 3;
1691
+ _context16.n = 3;
1514
1692
  break;
1515
1693
  }
1516
1694
  _t2 = (_yield$this$getTopic = _yield$this$getTopic.lastMessage) === null || _yield$this$getTopic === void 0;
1517
1695
  case 3:
1518
1696
  if (!_t2) {
1519
- _context14.n = 4;
1697
+ _context16.n = 4;
1520
1698
  break;
1521
1699
  }
1522
1700
  _t5 = void 0;
1523
- _context14.n = 5;
1701
+ _context16.n = 5;
1524
1702
  break;
1525
1703
  case 4:
1526
1704
  _t5 = _yield$this$getTopic.id;
1527
1705
  case 5:
1528
- return _context14.a(2, _t5);
1706
+ return _context16.a(2, _t5);
1529
1707
  }
1530
- }, _callee14, this);
1708
+ }, _callee16, this);
1531
1709
  }));
1532
1710
  function getLatestMessageId() {
1533
1711
  return _getLatestMessageId.apply(this, arguments);
@@ -1537,18 +1715,18 @@ var TopicHistoryWindow = /*#__PURE__*/function (_TraversableRemoteCol) {
1537
1715
  }, {
1538
1716
  key: "isLatestItemLoaded",
1539
1717
  value: function () {
1540
- var _isLatestItemLoaded = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee15() {
1718
+ var _isLatestItemLoaded = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee17() {
1541
1719
  var lastMessageId;
1542
- return _regenerator().w(function (_context15) {
1543
- while (1) switch (_context15.n) {
1720
+ return _regenerator().w(function (_context17) {
1721
+ while (1) switch (_context17.n) {
1544
1722
  case 0:
1545
- _context15.n = 1;
1723
+ _context17.n = 1;
1546
1724
  return this.getLatestMessageId();
1547
1725
  case 1:
1548
- lastMessageId = _context15.v;
1549
- return _context15.a(2, lastMessageId ? this.has(lastMessageId) : true);
1726
+ lastMessageId = _context17.v;
1727
+ return _context17.a(2, lastMessageId ? this.has(lastMessageId) : true);
1550
1728
  }
1551
- }, _callee15, this);
1729
+ }, _callee17, this);
1552
1730
  }));
1553
1731
  function isLatestItemLoaded() {
1554
1732
  return _isLatestItemLoaded.apply(this, arguments);
@@ -1558,10 +1736,10 @@ var TopicHistoryWindow = /*#__PURE__*/function (_TraversableRemoteCol) {
1558
1736
  }, {
1559
1737
  key: "handleNewMessage",
1560
1738
  value: function () {
1561
- var _handleNewMessage = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee16(ev) {
1739
+ var _handleNewMessage = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee18(ev) {
1562
1740
  var originalState;
1563
- return _regenerator().w(function (_context16) {
1564
- while (1) switch (_context16.n) {
1741
+ return _regenerator().w(function (_context18) {
1742
+ while (1) switch (_context18.n) {
1565
1743
  case 0:
1566
1744
  if ([WindowState.LATEST, WindowState.LIVE].includes(this.state) && ev.message.location.roomId === this.roomId && ev.message.location.topicId === this.topicId) {
1567
1745
  originalState = this.state;
@@ -1569,9 +1747,9 @@ var TopicHistoryWindow = /*#__PURE__*/function (_TraversableRemoteCol) {
1569
1747
  this.emitChangeWithDiff(true, originalState);
1570
1748
  }
1571
1749
  case 1:
1572
- return _context16.a(2);
1750
+ return _context18.a(2);
1573
1751
  }
1574
- }, _callee16, this);
1752
+ }, _callee18, this);
1575
1753
  }));
1576
1754
  function handleNewMessage(_x5) {
1577
1755
  return _handleNewMessage.apply(this, arguments);
@@ -1581,16 +1759,16 @@ var TopicHistoryWindow = /*#__PURE__*/function (_TraversableRemoteCol) {
1581
1759
  }, {
1582
1760
  key: "handleMessagesRedacted",
1583
1761
  value: function () {
1584
- var _handleMessagesRedacted = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee17(ev) {
1762
+ var _handleMessagesRedacted = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee19(ev) {
1585
1763
  var refTopicIds;
1586
- return _regenerator().w(function (_context17) {
1587
- while (1) switch (_context17.n) {
1764
+ return _regenerator().w(function (_context19) {
1765
+ while (1) switch (_context19.n) {
1588
1766
  case 0:
1589
1767
  if (!(ev.location.topicId !== this.topicId || ev.location.roomId !== this.roomId)) {
1590
- _context17.n = 1;
1768
+ _context19.n = 1;
1591
1769
  break;
1592
1770
  }
1593
- return _context17.a(2);
1771
+ return _context19.a(2);
1594
1772
  case 1:
1595
1773
  refTopicIds = this.items.filter(function (msg) {
1596
1774
  return msg.topicRef && ev.ids.includes(msg.id);
@@ -1599,19 +1777,19 @@ var TopicHistoryWindow = /*#__PURE__*/function (_TraversableRemoteCol) {
1599
1777
  });
1600
1778
  this["delete"].apply(this, TopicHistoryWindow_toConsumableArray(ev.ids));
1601
1779
  if (!(this.length === 0)) {
1602
- _context17.n = 2;
1780
+ _context19.n = 2;
1603
1781
  break;
1604
1782
  }
1605
- _context17.n = 2;
1783
+ _context19.n = 2;
1606
1784
  return this.resetToLatest();
1607
1785
  case 2:
1608
1786
  if (refTopicIds.length > 0) {
1609
1787
  this.eventTarget.emit('reftopicsdeleted', refTopicIds);
1610
1788
  }
1611
1789
  case 3:
1612
- return _context17.a(2);
1790
+ return _context19.a(2);
1613
1791
  }
1614
- }, _callee17, this);
1792
+ }, _callee19, this);
1615
1793
  }));
1616
1794
  function handleMessagesRedacted(_x6) {
1617
1795
  return _handleMessagesRedacted.apply(this, arguments);
@@ -1651,6 +1829,7 @@ var RoomMessagesHistory = /*#__PURE__*/function () {
1651
1829
  RoomMessagesHistory_classCallCheck(this, RoomMessagesHistory);
1652
1830
  RoomMessagesHistory_defineProperty(this, "historyWindows", new IndexedCollection());
1653
1831
  RoomMessagesHistory_defineProperty(this, "traverseLock", false);
1832
+ RoomMessagesHistory_defineProperty(this, "timeLimitedHistory", false);
1654
1833
  this.room = room;
1655
1834
  this.tracker = tracker;
1656
1835
  this.tracker.client.on('RoomUpdated', function (ev) {
@@ -1662,7 +1841,7 @@ var RoomMessagesHistory = /*#__PURE__*/function () {
1662
1841
  this.tracker.client.on('TopicDeleted', function (ev) {
1663
1842
  return _this.handleTopicDeleted(ev);
1664
1843
  });
1665
- this.updateTraverseLock(this.room);
1844
+ this.updateHistoryMode(this.room);
1666
1845
  if (this.room.defaultTopic) {
1667
1846
  this.createHistoryWindowForTopic(this.room.defaultTopic);
1668
1847
  }
@@ -1712,9 +1891,19 @@ var RoomMessagesHistory = /*#__PURE__*/function () {
1712
1891
  *
1713
1892
  * The window bindings are preserved; only windows that the application had
1714
1893
  * actually pulled to the latest page (state === LATEST) are refreshed, with
1715
- * a single resetToLatest instead of a chain of catch-up requests. Windows
1716
- * that were never pulled (LIVE) or belong to an ephemeral room are left
1717
- * untouched so their in-memory context survives the reconnect.
1894
+ * a single request instead of a chain of catch-up requests. Windows that
1895
+ * were never pulled (LIVE) or belong to an ephemeral room are left untouched
1896
+ * so their in-memory context survives the reconnect.
1897
+ *
1898
+ * How a refreshed window is rebuilt depends on the room history mode: rooms
1899
+ * keeping the full history are simply reset to the latest page (it can
1900
+ * always be traversed back on demand), while rooms with a time-limited
1901
+ * history (MaxAge) load the messages missed during the downtime on top of
1902
+ * the already loaded ones, with the messages returned in both deduplicated.
1903
+ * The maxAge retention applies to what the server serves - so that users
1904
+ * joining later do not see the older conversation - and never to what this
1905
+ * client already has: messages the user witnessed stay in the window until
1906
+ * they are pushed out by its own size limit.
1718
1907
  */
1719
1908
  )
1720
1909
  }, {
@@ -1726,14 +1915,14 @@ var RoomMessagesHistory = /*#__PURE__*/function () {
1726
1915
  while (1) switch (_context2.p = _context2.n) {
1727
1916
  case 0:
1728
1917
  this.room = room;
1729
- this.updateTraverseLock(room);
1918
+ this.updateHistoryMode(room);
1730
1919
  if (this.room.defaultTopic) {
1731
1920
  this.createHistoryWindowForTopic(this.room.defaultTopic);
1732
1921
  }
1733
1922
  _i = 0, _Array$from = Array.from(this.historyWindows.items);
1734
1923
  case 1:
1735
1924
  if (!(_i < _Array$from.length)) {
1736
- _context2.n = 8;
1925
+ _context2.n = 11;
1737
1926
  break;
1738
1927
  }
1739
1928
  _Array$from$_i = RoomMessagesHistory_slicedToArray(_Array$from[_i], 2), window = _Array$from$_i[1];
@@ -1745,28 +1934,40 @@ var RoomMessagesHistory = /*#__PURE__*/function () {
1745
1934
  _context2.n = 4;
1746
1935
  break;
1747
1936
  }
1748
- return _context2.a(3, 7);
1937
+ return _context2.a(3, 10);
1749
1938
  case 4:
1750
- if (!(window.state === WindowState.LATEST)) {
1939
+ if (!(window.state !== WindowState.LATEST)) {
1751
1940
  _context2.n = 5;
1752
1941
  break;
1753
1942
  }
1754
- _context2.n = 5;
1755
- return window.resetToLatest(true);
1943
+ return _context2.a(3, 10);
1756
1944
  case 5:
1757
- _context2.n = 7;
1758
- break;
1945
+ if (!this.timeLimitedHistory) {
1946
+ _context2.n = 7;
1947
+ break;
1948
+ }
1949
+ _context2.n = 6;
1950
+ return window.resyncToLatest();
1759
1951
  case 6:
1760
- _context2.p = 6;
1761
- _t = _context2.v;
1952
+ _context2.n = 8;
1953
+ break;
1762
1954
  case 7:
1955
+ _context2.n = 8;
1956
+ return window.resetToLatest(true);
1957
+ case 8:
1958
+ _context2.n = 10;
1959
+ break;
1960
+ case 9:
1961
+ _context2.p = 9;
1962
+ _t = _context2.v;
1963
+ case 10:
1763
1964
  _i++;
1764
1965
  _context2.n = 1;
1765
1966
  break;
1766
- case 8:
1967
+ case 11:
1767
1968
  return _context2.a(2);
1768
1969
  }
1769
- }, _callee2, this, [[2, 6]]);
1970
+ }, _callee2, this, [[2, 9]]);
1770
1971
  }));
1771
1972
  function resync(_x2) {
1772
1973
  return _resync.apply(this, arguments);
@@ -1786,7 +1987,7 @@ var RoomMessagesHistory = /*#__PURE__*/function () {
1786
1987
  break;
1787
1988
  }
1788
1989
  this.room = ev.room;
1789
- this.updateTraverseLock(ev.room);
1990
+ this.updateHistoryMode(ev.room);
1790
1991
  if (ev.room.defaultTopic) {
1791
1992
  this.createHistoryWindowForTopic(ev.room.defaultTopic);
1792
1993
  }
@@ -1864,9 +2065,11 @@ var RoomMessagesHistory = /*#__PURE__*/function () {
1864
2065
  }
1865
2066
  }
1866
2067
  }, {
1867
- key: "updateTraverseLock",
1868
- value: function updateTraverseLock(room) {
1869
- this.traverseLock = room.history.mode === 'Ephemeral';
2068
+ key: "updateHistoryMode",
2069
+ value: function updateHistoryMode(room) {
2070
+ var _room$history, _room$history2;
2071
+ this.traverseLock = ((_room$history = room.history) === null || _room$history === void 0 ? void 0 : _room$history.mode) === 'Ephemeral';
2072
+ this.timeLimitedHistory = ((_room$history2 = room.history) === null || _room$history2 === void 0 ? void 0 : _room$history2.mode) === 'MaxAge';
1870
2073
  }
1871
2074
  }]);
1872
2075
  }();