saltfish 0.3.36 → 0.3.38

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.
@@ -2846,9 +2846,9 @@ class PlaylistOrchestrator {
2846
2846
  this.managers.cursorManager.setColor(updatedStore.manifest.cursorColor);
2847
2847
  }
2848
2848
  const isTriggeredAutomatically = finalOptions._triggeredByTriggerManager === true;
2849
- if (updatedStore.manifest.idleMode) {
2850
- const isFirstStep = updatedStore.currentStepId === ((_e = updatedStore.manifest.steps[0]) == null ? void 0 : _e.id);
2851
- if (updatedStore.manifest.compactFirstStep && isFirstStep) {
2849
+ const isFirstStep = updatedStore.currentStepId === ((_e = updatedStore.manifest.steps[0]) == null ? void 0 : _e.id);
2850
+ if (updatedStore.manifest.idleMode && isFirstStep) {
2851
+ if (updatedStore.manifest.compactFirstStep) {
2852
2852
  const playerElement = this.managers.uiManager.getPlayerElement();
2853
2853
  playerElement == null ? void 0 : playerElement.classList.add("sf-player--compact");
2854
2854
  if (updatedStore.manifest.compactLabel) {
@@ -2911,6 +2911,51 @@ class PlaylistOrchestrator {
2911
2911
  destroy() {
2912
2912
  }
2913
2913
  }
2914
+ function validateUrlRequirement(urlRequirement) {
2915
+ const { pattern, matchType } = urlRequirement;
2916
+ if (!pattern) {
2917
+ return true;
2918
+ }
2919
+ const currentUrl = window.location.href;
2920
+ const currentPath = window.location.pathname;
2921
+ if (matchType === "regex") {
2922
+ try {
2923
+ const regex = new RegExp(pattern);
2924
+ const fullUrlMatch = regex.test(currentUrl);
2925
+ const pathMatch = regex.test(currentPath);
2926
+ const matches2 = fullUrlMatch || pathMatch;
2927
+ log(`urlValidation: Result (regex) - matches: ${matches2}`);
2928
+ return matches2;
2929
+ } catch (error2) {
2930
+ return false;
2931
+ }
2932
+ }
2933
+ if (matchType === "contains") {
2934
+ const matches2 = currentUrl.includes(pattern) || currentPath.includes(pattern);
2935
+ return matches2;
2936
+ }
2937
+ const matches = currentUrl === pattern || currentPath === pattern;
2938
+ return matches;
2939
+ }
2940
+ async function validateUrlRequirementWithRetry(urlRequirement, maxRetries = 20, retryDelay = 100) {
2941
+ if (!urlRequirement) {
2942
+ return true;
2943
+ }
2944
+ for (let attempt = 0; attempt < maxRetries; attempt++) {
2945
+ if (validateUrlRequirement(urlRequirement)) {
2946
+ return true;
2947
+ }
2948
+ if (attempt < maxRetries - 1) {
2949
+ await new Promise((resolve) => setTimeout(resolve, retryDelay));
2950
+ const saltfishPlayer = window._saltfishPlayer;
2951
+ if (!saltfishPlayer) {
2952
+ return false;
2953
+ }
2954
+ }
2955
+ }
2956
+ log(`urlValidation: Expected pattern: '${urlRequirement.pattern}' (matchType: ${urlRequirement.matchType})`);
2957
+ return false;
2958
+ }
2914
2959
  class StateMachineActionHandler {
2915
2960
  constructor(managers) {
2916
2961
  __publicField(this, "managers");
@@ -3147,47 +3192,24 @@ class StateMachineActionHandler {
3147
3192
  if (!step.urlRequirement) {
3148
3193
  return true;
3149
3194
  }
3150
- const { pattern, matchType } = step.urlRequirement;
3151
- if (!pattern) {
3152
- return true;
3153
- }
3154
- const checkUrl = () => {
3155
- const currentUrl = window.location.href;
3156
- const currentPath = window.location.pathname;
3157
- let matches = false;
3158
- if (matchType === "regex") {
3159
- try {
3160
- const regex = new RegExp(pattern);
3161
- matches = regex.test(currentUrl) || regex.test(currentPath);
3162
- } catch (error2) {
3163
- }
3164
- } else if (matchType === "contains") {
3165
- matches = currentUrl.includes(pattern) || currentPath.includes(pattern);
3166
- } else {
3167
- matches = currentUrl === pattern || currentPath === pattern;
3168
- }
3169
- return matches;
3170
- };
3171
- const maxRetries = 20;
3172
- const retryDelay = 100;
3173
- for (let attempt = 0; attempt < maxRetries; attempt++) {
3174
- if (checkUrl()) {
3175
- return true;
3176
- }
3177
- if (attempt < maxRetries - 1) {
3178
- await new Promise((resolve) => setTimeout(resolve, retryDelay));
3179
- const saltfishPlayer2 = window._saltfishPlayer;
3180
- if (!saltfishPlayer2) {
3181
- return false;
3195
+ log(`StateMachineActionHandler: Validating URL requirement for step ${step.id} with retry logic`);
3196
+ this.managers.transitionManager.startStateMachineValidation();
3197
+ try {
3198
+ const isValid = await validateUrlRequirementWithRetry(step.urlRequirement);
3199
+ if (!isValid) {
3200
+ log(`StateMachineActionHandler: URL requirement validation failed for step '${step.id}'`);
3201
+ log(`StateMachineActionHandler: Exiting playlist and closing player`);
3202
+ const saltfishPlayer = window._saltfishPlayer;
3203
+ if (saltfishPlayer && typeof saltfishPlayer.destroy === "function") {
3204
+ saltfishPlayer.destroy();
3205
+ } else {
3206
+ log("StateMachineActionHandler: Warning - Could not find SaltfishPlayer instance to destroy");
3182
3207
  }
3183
3208
  }
3209
+ return isValid;
3210
+ } finally {
3211
+ this.managers.transitionManager.endStateMachineValidation();
3184
3212
  }
3185
- log(`StateMachineActionHandler: URL requirement validation failed after ${maxRetries} retries for step '${step.id}'`);
3186
- const saltfishPlayer = window._saltfishPlayer;
3187
- if (saltfishPlayer && typeof saltfishPlayer.destroy === "function") {
3188
- saltfishPlayer.destroy();
3189
- }
3190
- return false;
3191
3213
  }
3192
3214
  // Private action handler methods
3193
3215
  async handleStartVideoPlayback(context) {
@@ -8240,7 +8262,10 @@ class InteractionManager {
8240
8262
  anonymousData.watchedPlaylists[currentStore.manifest.id] = {
8241
8263
  status: "in_progress",
8242
8264
  currentStepId: buttonConfig.action.target,
8265
+ timestamp: Date.now(),
8266
+ // Use timestamp for consistency with checkAndResumeInProgressPlaylist
8243
8267
  lastProgressAt: Date.now()
8268
+ // Keep for backward compatibility
8244
8269
  };
8245
8270
  this.storageManager.setAnonymousUserData(anonymousData);
8246
8271
  log(`InteractionManager: Updated anonymous user watchedPlaylists for step ${buttonConfig.action.target}`);
@@ -8878,12 +8903,17 @@ class TransitionManager {
8878
8903
  __publicField(this, "activeTransitions", /* @__PURE__ */ new Map());
8879
8904
  // Track current transition state
8880
8905
  __publicField(this, "waitingForInteraction", false);
8906
+ // Track when StateMachineActionHandler is validating to avoid race conditions
8907
+ __publicField(this, "isStateMachineValidating", false);
8881
8908
  // Reference to TriggerManager for coordinating playlist triggers
8882
8909
  __publicField(this, "triggerManager", null);
8883
8910
  /**
8884
8911
  * Handles URL changes by checking active URL path transitions and playlist triggers
8885
8912
  */
8886
8913
  __publicField(this, "handleURLChange", () => {
8914
+ if (this.isStateMachineValidating) {
8915
+ return;
8916
+ }
8887
8917
  const urlPathTransitions = Array.from(this.activeTransitions.entries()).filter(([_, transition]) => {
8888
8918
  var _a;
8889
8919
  return ((_a = transition.data) == null ? void 0 : _a.type) === "url-path";
@@ -9156,37 +9186,6 @@ class TransitionManager {
9156
9186
  const pathMatch = regex.test(currentPath);
9157
9187
  return fullUrlMatch || pathMatch;
9158
9188
  }
9159
- /**
9160
- * Validates if the current URL matches a URL requirement
9161
- * @param urlRequirement - The URL requirement to validate against
9162
- * @returns true if URL matches, false otherwise
9163
- */
9164
- validateUrlRequirement(urlRequirement) {
9165
- const { pattern, matchType } = urlRequirement;
9166
- if (!pattern) {
9167
- return true;
9168
- }
9169
- const currentUrl = window.location.href;
9170
- const currentPath = window.location.pathname;
9171
- if (matchType === "regex") {
9172
- try {
9173
- const regex = new RegExp(pattern);
9174
- const fullUrlMatch = regex.test(currentUrl);
9175
- const pathMatch = regex.test(currentPath);
9176
- const matches2 = fullUrlMatch || pathMatch;
9177
- log(`TransitionManager: URL requirement validation (regex) - matches: ${matches2}`);
9178
- return matches2;
9179
- } catch (error2) {
9180
- return false;
9181
- }
9182
- }
9183
- if (matchType === "contains") {
9184
- const matches2 = currentUrl.includes(pattern) || currentPath.includes(pattern);
9185
- return matches2;
9186
- }
9187
- const matches = currentUrl === pattern || currentPath === pattern;
9188
- return matches;
9189
- }
9190
9189
  /**
9191
9190
  * Handles URL requirement validation failure by exiting and closing the playlist
9192
9191
  * @param stepId - The step ID that failed validation
@@ -9201,8 +9200,9 @@ class TransitionManager {
9201
9200
  }
9202
9201
  }
9203
9202
  /**
9204
- * Validates the URL requirement for the current step
9205
- * @returns true if validation passes or no requirement exists, false if validation fails
9203
+ * Validates the URL requirement for the current step (immediate, no retries)
9204
+ * Used for external navigation detection - should close immediately if URL doesn't match
9205
+ * @returns boolean - true if validation passes or no requirement exists, false if validation fails
9206
9206
  */
9207
9207
  validateCurrentStepUrl() {
9208
9208
  const store = getSaltfishStore();
@@ -9215,7 +9215,7 @@ class TransitionManager {
9215
9215
  if (!currentStep || !currentStep.urlRequirement) {
9216
9216
  return true;
9217
9217
  }
9218
- const isValid = this.validateUrlRequirement(currentStep.urlRequirement);
9218
+ const isValid = validateUrlRequirement(currentStep.urlRequirement);
9219
9219
  if (!isValid) {
9220
9220
  this.handleUrlRequirementFailure(currentStepId, currentStep.urlRequirement);
9221
9221
  }
@@ -9300,6 +9300,19 @@ class TransitionManager {
9300
9300
  reset() {
9301
9301
  this.cleanupTransitions();
9302
9302
  }
9303
+ /**
9304
+ * Marks the start of StateMachineActionHandler validation to prevent race conditions
9305
+ * TransitionManager will skip validation while this flag is set
9306
+ */
9307
+ startStateMachineValidation() {
9308
+ this.isStateMachineValidating = true;
9309
+ }
9310
+ /**
9311
+ * Marks the end of StateMachineActionHandler validation
9312
+ */
9313
+ endStateMachineValidation() {
9314
+ this.isStateMachineValidating = false;
9315
+ }
9303
9316
  /**
9304
9317
  * Destroys the transition manager and cleans up resources
9305
9318
  */
@@ -11774,7 +11787,7 @@ const SaltfishPlayer$1 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.de
11774
11787
  __proto__: null,
11775
11788
  SaltfishPlayer
11776
11789
  }, Symbol.toStringTag, { value: "Module" }));
11777
- const version = "0.3.36";
11790
+ const version = "0.3.38";
11778
11791
  const packageJson = {
11779
11792
  version
11780
11793
  };