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