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.
- package/dist/core/services/PlaylistOrchestrator.d.ts.map +1 -1
- package/dist/core/services/StateMachineActionHandler.d.ts.map +1 -1
- package/dist/managers/InteractionManager.d.ts.map +1 -1
- package/dist/managers/TransitionManager.d.ts +13 -8
- package/dist/managers/TransitionManager.d.ts.map +1 -1
- package/dist/player.js +2 -2
- package/dist/player.min.js +2 -2
- package/dist/saltfish-playlist-player.es.js +89 -76
- package/dist/saltfish-playlist-player.umd.js +1 -1
- package/dist/utils/urlValidation.d.ts +16 -0
- package/dist/utils/urlValidation.d.ts.map +1 -0
- package/package.json +1 -1
|
@@ -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
|
-
|
|
2850
|
-
|
|
2851
|
-
if (updatedStore.manifest.compactFirstStep
|
|
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
|
-
|
|
3151
|
-
|
|
3152
|
-
|
|
3153
|
-
|
|
3154
|
-
|
|
3155
|
-
|
|
3156
|
-
|
|
3157
|
-
|
|
3158
|
-
|
|
3159
|
-
|
|
3160
|
-
|
|
3161
|
-
|
|
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
|
-
*
|
|
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 =
|
|
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.
|
|
11790
|
+
const version = "0.3.38";
|
|
11778
11791
|
const packageJson = {
|
|
11779
11792
|
version
|
|
11780
11793
|
};
|