@mushi-mushi/web 1.7.5 → 1.7.7

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.cjs CHANGED
@@ -3142,6 +3142,15 @@ var optedIn = false;
3142
3142
  var tierCache = null;
3143
3143
  var tierCacheTime = 0;
3144
3144
  var TIER_CACHE_TTL = 5 * 60 * 1e3;
3145
+ var rewardsApiBackoffUntil = 0;
3146
+ var REWARDS_4XX_BACKOFF_MS = 15 * 60 * 1e3;
3147
+ function isRewardsApiBackedOff() {
3148
+ return Date.now() < rewardsApiBackoffUntil;
3149
+ }
3150
+ function noteRewardsApiFailure(code) {
3151
+ if (!code?.startsWith("HTTP_4")) return;
3152
+ rewardsApiBackoffUntil = Date.now() + REWARDS_4XX_BACKOFF_MS;
3153
+ }
3145
3154
  var seenRoutes = /* @__PURE__ */ new Set();
3146
3155
  function getConsentKey(projectId) {
3147
3156
  return `mushi_rewards_consent_${projectId}`;
@@ -3246,14 +3255,22 @@ async function flush(ctx) {
3246
3255
  } catch {
3247
3256
  }
3248
3257
  }
3258
+ if (isRewardsApiBackedOff()) return;
3249
3259
  const batch = pendingEvents.splice(0, 100);
3250
3260
  try {
3251
- await ctx.client.submitActivity(currentUserId, batch, {
3261
+ const result = await ctx.client.submitActivity(currentUserId, batch, {
3252
3262
  userTraits: currentUserTraits ?? void 0,
3253
3263
  reporterTokenHash: reporterTokenHash ?? void 0,
3254
3264
  optedIn: true,
3255
3265
  hostJwt: hostJwt ?? void 0
3256
3266
  });
3267
+ if (!result.ok) {
3268
+ noteRewardsApiFailure(result.error?.code);
3269
+ const permanent = result.error?.code?.startsWith("HTTP_4");
3270
+ if (!permanent) {
3271
+ pendingEvents.unshift(...batch.slice(0, 50));
3272
+ }
3273
+ }
3257
3274
  } catch {
3258
3275
  pendingEvents.unshift(...batch.slice(0, 50));
3259
3276
  }
@@ -3264,13 +3281,14 @@ async function getTier(userId) {
3264
3281
  return fetchAndCacheTier(userId);
3265
3282
  }
3266
3283
  async function fetchAndCacheTier(userId) {
3267
- if (!apiClient) return null;
3284
+ if (!apiClient || isRewardsApiBackedOff()) return null;
3268
3285
  const res = await apiClient.getMyTier(userId);
3269
3286
  if (res.ok && res.data) {
3270
3287
  tierCache = res.data;
3271
3288
  tierCacheTime = Date.now();
3272
3289
  return tierCache;
3273
3290
  }
3291
+ noteRewardsApiFailure(res.error?.code);
3274
3292
  return null;
3275
3293
  }
3276
3294
  var routeObserver = null;
@@ -3674,6 +3692,7 @@ var DEFAULT_REDACT_SELECTORS = [
3674
3692
  ];
3675
3693
  function buildPrivacySafeDocument(privacy) {
3676
3694
  const clone = document.documentElement.cloneNode(true);
3695
+ clone.querySelector("#mushi-mushi-widget")?.remove();
3677
3696
  const redactSelectors = privacy?.redactSelectors !== void 0 ? privacy.redactSelectors : DEFAULT_REDACT_SELECTORS;
3678
3697
  for (const selector of redactSelectors) {
3679
3698
  for (const el of safeQueryAll(clone, selector)) {
@@ -4763,7 +4782,7 @@ function createProactiveManager(config = {}) {
4763
4782
 
4764
4783
  // src/version.ts
4765
4784
  var MUSHI_SDK_PACKAGE = "@mushi-mushi/web";
4766
- var MUSHI_SDK_VERSION = "1.7.5" ;
4785
+ var MUSHI_SDK_VERSION = "1.7.7" ;
4767
4786
 
4768
4787
  // src/mushi.ts
4769
4788
  var instance = null;
@@ -4944,15 +4963,43 @@ function createInstance(config) {
4944
4963
  });
4945
4964
  let detachAutoBreadcrumbs = null;
4946
4965
  detachAutoBreadcrumbs = installAutoBreadcrumbs(breadcrumbs);
4966
+ async function takeScreenshotWithoutChrome() {
4967
+ if (!screenshotCap) return null;
4968
+ const panelWasVisible = widget.getIsOpen();
4969
+ if (panelWasVisible) widget.hidePanel();
4970
+ const host = document.getElementById("mushi-mushi-widget");
4971
+ const prevVisibility = host?.style.visibility ?? "";
4972
+ if (host) host.style.visibility = "hidden";
4973
+ await new Promise((resolve) => {
4974
+ requestAnimationFrame(() => requestAnimationFrame(() => resolve()));
4975
+ });
4976
+ try {
4977
+ return await screenshotCap.take();
4978
+ } finally {
4979
+ if (host) host.style.visibility = prevVisibility;
4980
+ if (panelWasVisible) widget.showPanel();
4981
+ }
4982
+ }
4983
+ async function autoCaptureScreenshot(when) {
4984
+ const mode = activeConfig.capture?.screenshot;
4985
+ if (!screenshotCap || mode === "off" || pendingScreenshot) return;
4986
+ if (when === "open" && mode !== "auto") return;
4987
+ if (when === "submit" && mode !== "on-report" && mode !== "auto") return;
4988
+ log.debug("Auto-capturing screenshot", { when, mode });
4989
+ pendingScreenshot = await takeScreenshotWithoutChrome();
4990
+ widget.setScreenshotAttached(pendingScreenshot !== null);
4991
+ }
4947
4992
  widget = new MushiWidget(bootstrapConfig.widget, {
4948
4993
  onSubmit: async ({ category, description, intent }) => {
4949
4994
  log.info("Report submitted", { category, intent });
4950
4995
  proactiveManager?.recordSubmission();
4996
+ await autoCaptureScreenshot("submit");
4951
4997
  const outcome = await submitReport(category, description, intent);
4952
4998
  return outcome ?? { reportId: null, queuedOffline: true };
4953
4999
  },
4954
5000
  onOpen: () => {
4955
5001
  log.debug("Widget opened");
5002
+ void autoCaptureScreenshot("open");
4956
5003
  emit("widget:opened");
4957
5004
  },
4958
5005
  onClose: () => {
@@ -4969,7 +5016,7 @@ function createInstance(config) {
4969
5016
  onScreenshotRequest: async () => {
4970
5017
  if (!screenshotCap || activeConfig.capture?.screenshot === "off") return;
4971
5018
  log.debug("Taking screenshot");
4972
- pendingScreenshot = await screenshotCap.take();
5019
+ pendingScreenshot = await takeScreenshotWithoutChrome();
4973
5020
  widget.setScreenshotAttached(pendingScreenshot !== null);
4974
5021
  },
4975
5022
  onScreenshotRemove: () => {