@trycourier/courier-ui-inbox 2.4.0 → 2.4.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -2,7 +2,7 @@ var __defProp = Object.defineProperty;
2
2
  var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
3
3
  var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
4
4
  import { Courier, InboxMessageEvent } from "@trycourier/courier-js";
5
- import { Courier as Courier2 } from "@trycourier/courier-js";
5
+ import { Courier as Courier2, DEFAULT_COURIER_API_URLS, EU_COURIER_API_URLS, getCourierApiUrls, getCourierApiUrlsForRegion } from "@trycourier/courier-js";
6
6
  import { registerElement, CourierBaseElement, CourierIconButton, CourierIcon, CourierIconSVGs, CourierButton, injectGlobalStyle, CourierFactoryElement, CourierInfoState, CourierColors, CourierThemeManager } from "@trycourier/courier-ui-core";
7
7
  function copyMessage(message) {
8
8
  const copy = {
@@ -436,12 +436,13 @@ class CourierInboxDataset {
436
436
  }
437
437
  const beforeQualifies = this.messageQualifiesForDataset(beforeMessage);
438
438
  if (beforeQualifies) {
439
- this.totalUnreadCount += this.calculateUnreadChange(beforeMessage, afterMessage);
439
+ if (!beforeMessage.read) {
440
+ this.totalUnreadCount -= 1;
441
+ }
440
442
  this._datastoreListeners.forEach((listener) => {
441
- var _a, _b, _c, _d, _e, _f;
442
- (_b = (_a = listener.events).onMessageUpdate) == null ? void 0 : _b.call(_a, newMessage, index, this._id);
443
- (_d = (_c = listener.events).onUnreadCountChange) == null ? void 0 : _d.call(_c, this.totalUnreadCount, this._id);
444
- (_f = (_e = listener.events).onTotalUnreadCountChange) == null ? void 0 : _f.call(_e, CourierInboxDatastore.shared.totalUnreadCount);
443
+ var _a, _b, _c, _d;
444
+ (_b = (_a = listener.events).onUnreadCountChange) == null ? void 0 : _b.call(_a, this.totalUnreadCount, this._id);
445
+ (_d = (_c = listener.events).onTotalUnreadCountChange) == null ? void 0 : _d.call(_c, CourierInboxDatastore.shared.totalUnreadCount);
445
446
  });
446
447
  }
447
448
  return false;
@@ -623,6 +624,8 @@ const _CourierInboxDatastore = class _CourierInboxDatastore {
623
624
  __publicField(this, "_datasets", /* @__PURE__ */ new Map());
624
625
  __publicField(this, "_listeners", []);
625
626
  __publicField(this, "_removeMessageEventListener");
627
+ __publicField(this, "_pendingOpenMessageIds", /* @__PURE__ */ new Set());
628
+ __publicField(this, "_openBatchTimer", null);
626
629
  /**
627
630
  * Global message store is a map of Message ID to Message for all messages
628
631
  * that have been loaded.
@@ -794,24 +797,64 @@ const _CourierInboxDatastore = class _CourierInboxDatastore {
794
797
  }
795
798
  /**
796
799
  * Mark a message as opened.
800
+ *
801
+ * The local state is updated optimistically and the server call is
802
+ * batched: multiple opens arriving within a short window
803
+ * are collected and flushed as a single GraphQL request.
804
+ *
797
805
  * @param message - The message to mark as opened
798
806
  */
799
- async openMessage({ message }) {
807
+ openMessage({ message }) {
800
808
  if (message.opened) {
801
809
  return;
802
810
  }
803
811
  const beforeMessage = this._globalMessages.get(message.messageId);
804
- if (!beforeMessage) {
812
+ if (!beforeMessage || beforeMessage.opened) {
805
813
  return;
806
814
  }
807
- await this.executeWithRollback(async () => {
808
- var _a;
809
- const afterMessage = copyMessage(beforeMessage);
810
- afterMessage.opened = _CourierInboxDatastore.getISONow();
811
- this._globalMessages.set(message.messageId, afterMessage);
812
- this.updateDatasetsWithMessageChange(beforeMessage, afterMessage);
813
- await ((_a = Courier.shared.client) == null ? void 0 : _a.inbox.open({ messageId: message.messageId }));
814
- });
815
+ const afterMessage = copyMessage(beforeMessage);
816
+ afterMessage.opened = _CourierInboxDatastore.getISONow();
817
+ this._globalMessages.set(message.messageId, afterMessage);
818
+ this.updateDatasetsWithMessageChange(beforeMessage, afterMessage);
819
+ this._pendingOpenMessageIds.add(message.messageId);
820
+ this.scheduleBatchOpen();
821
+ }
822
+ scheduleBatchOpen() {
823
+ if (this._openBatchTimer !== null) {
824
+ clearTimeout(this._openBatchTimer);
825
+ }
826
+ this._openBatchTimer = setTimeout(() => {
827
+ this.flushBatchOpen();
828
+ }, _CourierInboxDatastore.OPEN_BATCH_DELAY_MS);
829
+ }
830
+ async flushBatchOpen() {
831
+ var _a, _b;
832
+ this._openBatchTimer = null;
833
+ const messageIds = Array.from(this._pendingOpenMessageIds);
834
+ this._pendingOpenMessageIds.clear();
835
+ if (messageIds.length === 0) return;
836
+ const maxSize = _CourierInboxDatastore.OPEN_BATCH_MAX_SIZE;
837
+ const chunks = [];
838
+ for (let i = 0; i < messageIds.length; i += maxSize) {
839
+ chunks.push(messageIds.slice(i, i + maxSize));
840
+ }
841
+ try {
842
+ await Promise.all(
843
+ chunks.map((chunk) => {
844
+ var _a2;
845
+ return (_a2 = Courier.shared.client) == null ? void 0 : _a2.inbox.batchOpen(chunk);
846
+ })
847
+ );
848
+ } catch (error) {
849
+ (_b = (_a = Courier.shared.client) == null ? void 0 : _a.options.logger) == null ? void 0 : _b.error(
850
+ `[${_CourierInboxDatastore.TAG}] Error batch opening messages:`,
851
+ error
852
+ );
853
+ this._listeners.forEach((listener) => {
854
+ var _a2, _b2;
855
+ (_b2 = (_a2 = listener.events).onError) == null ? void 0 : _b2.call(_a2, error);
856
+ });
857
+ }
815
858
  }
816
859
  /**
817
860
  * Unarchive a message.
@@ -891,6 +934,11 @@ const _CourierInboxDatastore = class _CourierInboxDatastore {
891
934
  this.updateDatasetsWithMessageChange(beforeMessage, afterMessage);
892
935
  }
893
936
  }
937
+ for (const dataset of this._datasets.values()) {
938
+ if (!dataset.getFilter().archived) {
939
+ dataset.setUnreadCount(0);
940
+ }
941
+ }
894
942
  await ((_a = Courier.shared.client) == null ? void 0 : _a.inbox.archiveAll());
895
943
  });
896
944
  }
@@ -909,6 +957,9 @@ const _CourierInboxDatastore = class _CourierInboxDatastore {
909
957
  this.updateDatasetsWithMessageChange(beforeMessage, afterMessage);
910
958
  }
911
959
  }
960
+ for (const dataset of this._datasets.values()) {
961
+ dataset.setUnreadCount(0);
962
+ }
912
963
  await ((_a = Courier.shared.client) == null ? void 0 : _a.inbox.readAll());
913
964
  });
914
965
  }
@@ -1100,6 +1151,17 @@ const _CourierInboxDatastore = class _CourierInboxDatastore {
1100
1151
  this.updateDatasetsWithMessageChange(beforeMessage, afterMessage);
1101
1152
  }
1102
1153
  }
1154
+ if (event === InboxMessageEvent.MarkAllRead) {
1155
+ for (const dataset of this._datasets.values()) {
1156
+ dataset.setUnreadCount(0);
1157
+ }
1158
+ } else if (event === InboxMessageEvent.ArchiveAll) {
1159
+ for (const dataset of this._datasets.values()) {
1160
+ if (!dataset.getFilter().archived) {
1161
+ dataset.setUnreadCount(0);
1162
+ }
1163
+ }
1164
+ }
1103
1165
  }
1104
1166
  /**
1105
1167
  * Update a single message across all datasets from an InboxMessageEvent.
@@ -1230,6 +1292,8 @@ const _CourierInboxDatastore = class _CourierInboxDatastore {
1230
1292
  }
1231
1293
  };
1232
1294
  __publicField(_CourierInboxDatastore, "TAG", "CourierInboxDatastore");
1295
+ __publicField(_CourierInboxDatastore, "OPEN_BATCH_DELAY_MS", 100);
1296
+ __publicField(_CourierInboxDatastore, "OPEN_BATCH_MAX_SIZE", 50);
1233
1297
  __publicField(_CourierInboxDatastore, "instance");
1234
1298
  let CourierInboxDatastore = _CourierInboxDatastore;
1235
1299
  class CourierInboxListItem extends CourierBaseElement {
@@ -1979,7 +2043,7 @@ function archiveMessage(message) {
1979
2043
  return CourierInboxDatastore.shared.archiveMessage({ message });
1980
2044
  }
1981
2045
  function openMessage(message) {
1982
- return CourierInboxDatastore.shared.openMessage({ message });
2046
+ CourierInboxDatastore.shared.openMessage({ message });
1983
2047
  }
1984
2048
  function defaultFeeds() {
1985
2049
  return [
@@ -2330,11 +2394,8 @@ class CourierInboxList extends CourierBaseElement {
2330
2394
  list.appendChild(paginationItem);
2331
2395
  }
2332
2396
  }
2333
- async openVisibleMessage(message) {
2334
- try {
2335
- await openMessage(message);
2336
- } catch (error) {
2337
- }
2397
+ openVisibleMessage(message) {
2398
+ openMessage(message);
2338
2399
  }
2339
2400
  // Factories
2340
2401
  setLoadingStateFactory(factory) {
@@ -4679,7 +4740,7 @@ class CourierInbox extends CourierBaseElement {
4679
4740
  this._themeManager.setMode(mode);
4680
4741
  }
4681
4742
  static get observedAttributes() {
4682
- return ["height", "light-theme", "dark-theme", "mode", "message-click", "message-action-click", "message-long-press"];
4743
+ return ["height", "light-theme", "dark-theme", "mode", "feeds", "message-click", "message-action-click", "message-long-press"];
4683
4744
  }
4684
4745
  resetInitialFeedAndTab() {
4685
4746
  if (!this._feeds.length) {
@@ -4843,6 +4904,7 @@ class CourierInbox extends CourierBaseElement {
4843
4904
  },
4844
4905
  onMessageClick: (message, index) => {
4845
4906
  var _a2;
4907
+ CourierInboxDatastore.shared.openMessage({ message });
4846
4908
  CourierInboxDatastore.shared.clickMessage({ message });
4847
4909
  this.dispatchEvent(new CustomEvent("message-click", {
4848
4910
  detail: { message, index },
@@ -5150,7 +5212,7 @@ class CourierInbox extends CourierBaseElement {
5150
5212
  });
5151
5213
  }
5152
5214
  attributeChangedCallback(name, oldValue, newValue) {
5153
- var _a, _b, _c, _d, _e, _f;
5215
+ var _a, _b, _c, _d, _e, _f, _g, _h;
5154
5216
  if (oldValue === newValue) return;
5155
5217
  switch (name) {
5156
5218
  case "height":
@@ -5190,6 +5252,20 @@ class CourierInbox extends CourierBaseElement {
5190
5252
  this._onMessageLongPress = void 0;
5191
5253
  }
5192
5254
  break;
5255
+ case "feeds":
5256
+ if (newValue) {
5257
+ try {
5258
+ const feeds = JSON.parse(newValue);
5259
+ if (this._datastoreListener) {
5260
+ this.setFeeds(feeds);
5261
+ } else {
5262
+ this._feeds = feeds;
5263
+ }
5264
+ } catch (error) {
5265
+ (_h = (_g = Courier.shared.client) == null ? void 0 : _g.options.logger) == null ? void 0 : _h.error("Failed to parse feeds attribute:", error);
5266
+ }
5267
+ }
5268
+ break;
5193
5269
  case "light-theme":
5194
5270
  if (newValue) {
5195
5271
  this.setLightTheme(JSON.parse(newValue));
@@ -5312,6 +5388,8 @@ class CourierInboxPopupMenu extends CourierBaseElement {
5312
5388
  __publicField(this, "_datastoreListener");
5313
5389
  // State
5314
5390
  __publicField(this, "_totalUnreadCount", 0);
5391
+ // Feeds (stored from attribute before inner inbox is created)
5392
+ __publicField(this, "_feeds");
5315
5393
  // Factories
5316
5394
  __publicField(this, "_popupMenuButtonFactory");
5317
5395
  __publicField(this, "handleOutsideClick", (event) => {
@@ -5360,7 +5438,7 @@ class CourierInboxPopupMenu extends CourierBaseElement {
5360
5438
  this._themeManager.setMode(mode);
5361
5439
  }
5362
5440
  static get observedAttributes() {
5363
- return ["popup-alignment", "message-click", "message-action-click", "message-long-press", "popup-width", "popup-height", "top", "right", "bottom", "left", "light-theme", "dark-theme", "mode"];
5441
+ return ["popup-alignment", "feeds", "message-click", "message-action-click", "message-long-press", "popup-width", "popup-height", "top", "right", "bottom", "left", "light-theme", "dark-theme", "mode"];
5364
5442
  }
5365
5443
  onComponentMounted() {
5366
5444
  this.readInitialThemeAttributes();
@@ -5370,6 +5448,9 @@ class CourierInboxPopupMenu extends CourierBaseElement {
5370
5448
  this._popup.className = "popup";
5371
5449
  this._inbox = new CourierInbox(this._themeManager);
5372
5450
  this._inbox.setAttribute("height", "100%");
5451
+ if (this._feeds) {
5452
+ this._inbox.setAttribute("feeds", JSON.stringify(this._feeds));
5453
+ }
5373
5454
  this.refreshTheme();
5374
5455
  this.appendChild(this._triggerButton);
5375
5456
  this.appendChild(this._popup);
@@ -5458,6 +5539,7 @@ class CourierInboxPopupMenu extends CourierBaseElement {
5458
5539
  `;
5459
5540
  }
5460
5541
  attributeChangedCallback(name, _, newValue) {
5542
+ var _a, _b;
5461
5543
  switch (name) {
5462
5544
  case "popup-alignment":
5463
5545
  if (this.isValidPosition(newValue)) {
@@ -5489,6 +5571,19 @@ class CourierInboxPopupMenu extends CourierBaseElement {
5489
5571
  this._left = newValue;
5490
5572
  this.updatePopupPosition();
5491
5573
  break;
5574
+ case "feeds":
5575
+ if (newValue) {
5576
+ try {
5577
+ const feeds = JSON.parse(newValue);
5578
+ this._feeds = feeds;
5579
+ if (this._inbox) {
5580
+ this._inbox.setFeeds(feeds);
5581
+ }
5582
+ } catch (error) {
5583
+ (_b = (_a = Courier.shared.client) == null ? void 0 : _a.options.logger) == null ? void 0 : _b.error("Failed to parse feeds attribute:", error);
5584
+ }
5585
+ }
5586
+ break;
5492
5587
  case "light-theme":
5493
5588
  if (newValue) {
5494
5589
  this.setLightTheme(JSON.parse(newValue));
@@ -5930,7 +6025,7 @@ class CourierInboxDatastoreEvents {
5930
6025
  }
5931
6026
  }
5932
6027
  Courier.shared.courierUserAgentName = "courier-ui-inbox";
5933
- Courier.shared.courierUserAgentVersion = "2.4.0";
6028
+ Courier.shared.courierUserAgentVersion = "2.4.2";
5934
6029
  export {
5935
6030
  Courier2 as Courier,
5936
6031
  CourierInbox,
@@ -5941,6 +6036,8 @@ export {
5941
6036
  CourierInboxListItem,
5942
6037
  CourierInboxPopupMenu,
5943
6038
  CourierInboxThemeManager,
6039
+ DEFAULT_COURIER_API_URLS,
6040
+ EU_COURIER_API_URLS,
5944
6041
  archiveMessage,
5945
6042
  clickMessage,
5946
6043
  defaultActions,
@@ -5948,6 +6045,8 @@ export {
5948
6045
  defaultFeeds,
5949
6046
  defaultLightTheme,
5950
6047
  defaultListItemActions,
6048
+ getCourierApiUrls,
6049
+ getCourierApiUrlsForRegion,
5951
6050
  markAsRead,
5952
6051
  markAsUnread,
5953
6052
  mergeTheme,