saltfish 0.2.73 → 0.2.74
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/PlayerInitializationService.d.ts.map +1 -1
- package/dist/core/services/StateMachineActionHandler.d.ts.map +1 -1
- package/dist/loaders/PlaylistLoader.d.ts.map +1 -1
- package/dist/managers/InteractionManager.d.ts.map +1 -1
- package/dist/managers/TransitionManager.d.ts +2 -1
- 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 +87 -39
- package/dist/saltfish-playlist-player.umd.js +1 -1
- package/dist/utils/progressUtils.d.ts +30 -0
- package/dist/utils/progressUtils.d.ts.map +1 -0
- package/package.json +1 -1
|
@@ -1525,6 +1525,36 @@ const useSaltfishStore = {
|
|
|
1525
1525
|
subscribe: saltfishStore.subscribe,
|
|
1526
1526
|
destroy: saltfishStore.destroy
|
|
1527
1527
|
};
|
|
1528
|
+
const MAX_PROGRESS_AGE_MS = 6e3;
|
|
1529
|
+
function parseProgressTimestamp(progressData) {
|
|
1530
|
+
if (!progressData) {
|
|
1531
|
+
return null;
|
|
1532
|
+
}
|
|
1533
|
+
if (progressData.lastProgressAt && typeof progressData.lastProgressAt === "object" && "_seconds" in progressData.lastProgressAt && "_nanoseconds" in progressData.lastProgressAt) {
|
|
1534
|
+
const firestoreTimestamp = progressData.lastProgressAt;
|
|
1535
|
+
return firestoreTimestamp._seconds * 1e3 + Math.floor(firestoreTimestamp._nanoseconds / 1e6);
|
|
1536
|
+
}
|
|
1537
|
+
if (progressData.timestamp && typeof progressData.timestamp === "number") {
|
|
1538
|
+
return progressData.timestamp;
|
|
1539
|
+
}
|
|
1540
|
+
if (progressData.lastProgressAt && typeof progressData.lastProgressAt === "number") {
|
|
1541
|
+
return progressData.lastProgressAt;
|
|
1542
|
+
}
|
|
1543
|
+
return null;
|
|
1544
|
+
}
|
|
1545
|
+
function isProgressRecent(progressData, maxAgeMs = MAX_PROGRESS_AGE_MS) {
|
|
1546
|
+
const timestampMs = parseProgressTimestamp(progressData);
|
|
1547
|
+
if (!timestampMs) {
|
|
1548
|
+
return { isValid: false, ageMs: null, timestampMs: null };
|
|
1549
|
+
}
|
|
1550
|
+
const currentTime = Date.now();
|
|
1551
|
+
const ageMs = currentTime - timestampMs;
|
|
1552
|
+
return {
|
|
1553
|
+
isValid: ageMs <= maxAgeMs,
|
|
1554
|
+
ageMs,
|
|
1555
|
+
timestampMs
|
|
1556
|
+
};
|
|
1557
|
+
}
|
|
1528
1558
|
class ErrorHandler {
|
|
1529
1559
|
/**
|
|
1530
1560
|
* Handles an error with consistent logging, reporting, and response
|
|
@@ -2042,40 +2072,19 @@ class PlayerInitializationService {
|
|
|
2042
2072
|
if (currentManifestId && currentState !== "idle" && currentState !== "error") {
|
|
2043
2073
|
return false;
|
|
2044
2074
|
}
|
|
2045
|
-
const currentTime = Date.now();
|
|
2046
|
-
const MAX_AGE_MS = 6e3;
|
|
2047
2075
|
const inProgressEntry = Object.entries(watchedPlaylists).find(([playlistId, status]) => {
|
|
2048
2076
|
if ((status == null ? void 0 : status.status) !== "in_progress") {
|
|
2049
2077
|
return false;
|
|
2050
2078
|
}
|
|
2051
|
-
|
|
2052
|
-
if (
|
|
2053
|
-
const firestoreTimestamp = status.lastProgressAt;
|
|
2054
|
-
timestampMs = firestoreTimestamp._seconds * 1e3 + Math.floor(firestoreTimestamp._nanoseconds / 1e6);
|
|
2055
|
-
} else if (status.timestamp && typeof status.timestamp === "number") {
|
|
2056
|
-
timestampMs = status.timestamp;
|
|
2057
|
-
} else if (status.lastProgressAt && typeof status.lastProgressAt === "number") {
|
|
2058
|
-
timestampMs = status.lastProgressAt;
|
|
2059
|
-
}
|
|
2060
|
-
if (!timestampMs) {
|
|
2061
|
-
return false;
|
|
2062
|
-
}
|
|
2063
|
-
const ageMs = currentTime - timestampMs;
|
|
2064
|
-
if (ageMs > MAX_AGE_MS) {
|
|
2079
|
+
const { isValid, ageMs } = isProgressRecent(status);
|
|
2080
|
+
if (!isValid) {
|
|
2065
2081
|
return false;
|
|
2066
2082
|
}
|
|
2067
2083
|
return true;
|
|
2068
2084
|
});
|
|
2069
2085
|
if (inProgressEntry) {
|
|
2070
2086
|
const [playlistId, status] = inProgressEntry;
|
|
2071
|
-
|
|
2072
|
-
const firestoreTimestamp = status.lastProgressAt;
|
|
2073
|
-
firestoreTimestamp._seconds * 1e3 + Math.floor(firestoreTimestamp._nanoseconds / 1e6);
|
|
2074
|
-
} else if ((status == null ? void 0 : status.timestamp) && typeof status.timestamp === "number") {
|
|
2075
|
-
status.timestamp;
|
|
2076
|
-
} else if ((status == null ? void 0 : status.lastProgressAt) && typeof status.lastProgressAt === "number") {
|
|
2077
|
-
status.lastProgressAt;
|
|
2078
|
-
}
|
|
2087
|
+
parseProgressTimestamp(status);
|
|
2079
2088
|
try {
|
|
2080
2089
|
if (this.playlistOrchestrator) {
|
|
2081
2090
|
await this.playlistOrchestrator.startPlaylist(playlistId);
|
|
@@ -2997,9 +3006,10 @@ class StateMachineActionHandler {
|
|
|
2997
3006
|
const completionPolicy = hasSpecialTransitions ? "manual" : "auto";
|
|
2998
3007
|
if (hasSpecialTransitions) {
|
|
2999
3008
|
log("StateMachineActionHandler: Setting up transitions immediately for step with special transitions");
|
|
3000
|
-
this.managers.transitionManager.setupTransitions(currentStep, false);
|
|
3009
|
+
this.managers.transitionManager.setupTransitions(currentStep, false, true);
|
|
3001
3010
|
}
|
|
3002
3011
|
this.managers.videoManager.setCompletionPolicy(completionPolicy, () => {
|
|
3012
|
+
var _a;
|
|
3003
3013
|
const store = useSaltfishStore.getState();
|
|
3004
3014
|
if (!hasSpecialTransitions) {
|
|
3005
3015
|
log("StateMachineActionHandler: Setting up transitions after video ended");
|
|
@@ -3014,10 +3024,38 @@ class StateMachineActionHandler {
|
|
|
3014
3024
|
});
|
|
3015
3025
|
}
|
|
3016
3026
|
} else {
|
|
3017
|
-
|
|
3018
|
-
|
|
3019
|
-
|
|
3020
|
-
|
|
3027
|
+
const timeoutTransition = currentStep.transitions.find((t) => t.type === "timeout");
|
|
3028
|
+
const hasGotoButtonWithUrl = (_a = currentStep.buttons) == null ? void 0 : _a.some(
|
|
3029
|
+
(button) => button.action.type === "goto" && button.action.url
|
|
3030
|
+
);
|
|
3031
|
+
if (timeoutTransition && !hasGotoButtonWithUrl) {
|
|
3032
|
+
const timeout = timeoutTransition.timeout || 0;
|
|
3033
|
+
log(`StateMachineActionHandler: Video ended, setting up timeout transition to ${timeoutTransition.nextStep} with ${timeout}ms delay`);
|
|
3034
|
+
setTimeout(() => {
|
|
3035
|
+
var _a2;
|
|
3036
|
+
const currentStore = useSaltfishStore.getState();
|
|
3037
|
+
if (currentStore.currentStepId === currentStep.id && (currentStore.currentState === "waitingForInteraction" || currentStore.currentState === "playing")) {
|
|
3038
|
+
log(`StateMachineActionHandler: Timeout expired (${timeout}ms), transitioning to ${timeoutTransition.nextStep}`);
|
|
3039
|
+
(_a2 = currentStore.goToStep) == null ? void 0 : _a2.call(currentStore, timeoutTransition.nextStep);
|
|
3040
|
+
} else {
|
|
3041
|
+
log(`StateMachineActionHandler: Timeout cancelled - step changed or state is ${currentStore.currentState}`);
|
|
3042
|
+
}
|
|
3043
|
+
}, timeout);
|
|
3044
|
+
store.sendStateMachineEvent({
|
|
3045
|
+
type: "VIDEO_FINISHED_WAIT",
|
|
3046
|
+
step: currentStep
|
|
3047
|
+
});
|
|
3048
|
+
} else {
|
|
3049
|
+
if (hasGotoButtonWithUrl) {
|
|
3050
|
+
log("StateMachineActionHandler: Video ended, has goto button with URL redirect - waiting for user to click button");
|
|
3051
|
+
} else {
|
|
3052
|
+
log("StateMachineActionHandler: Video ended, waiting for user interaction");
|
|
3053
|
+
}
|
|
3054
|
+
store.sendStateMachineEvent({
|
|
3055
|
+
type: "VIDEO_FINISHED_WAIT",
|
|
3056
|
+
step: currentStep
|
|
3057
|
+
});
|
|
3058
|
+
}
|
|
3021
3059
|
}
|
|
3022
3060
|
});
|
|
3023
3061
|
log("StateMachineActionHandler: Starting async video load");
|
|
@@ -7209,6 +7247,8 @@ class InteractionManager {
|
|
|
7209
7247
|
state.progress[state.manifest.id] = {
|
|
7210
7248
|
...state.progress[state.manifest.id],
|
|
7211
7249
|
lastStepId: buttonConfig.action.target,
|
|
7250
|
+
lastProgressAt: Date.now(),
|
|
7251
|
+
// Use timestamp for 6-second rule
|
|
7212
7252
|
lastVisited: (/* @__PURE__ */ new Date()).toISOString()
|
|
7213
7253
|
};
|
|
7214
7254
|
}
|
|
@@ -7962,17 +8002,20 @@ class TransitionManager {
|
|
|
7962
8002
|
* Sets up transitions for a step
|
|
7963
8003
|
* @param step - The step to set up transitions for
|
|
7964
8004
|
* @param triggerImmediately - Whether to immediately trigger non-interaction transitions
|
|
8005
|
+
* @param skipTimeouts - Whether to skip setting up timeout transitions (useful for manual policy steps)
|
|
7965
8006
|
*/
|
|
7966
|
-
setupTransitions(step, triggerImmediately = false) {
|
|
8007
|
+
setupTransitions(step, triggerImmediately = false, skipTimeouts = false) {
|
|
7967
8008
|
this.cleanupTransitions();
|
|
7968
|
-
log(`TransitionManager: Setting up transitions for step ${step.id}`);
|
|
8009
|
+
log(`TransitionManager: Setting up transitions for step ${step.id}${skipTimeouts ? " (skipping timeouts)" : ""}`);
|
|
7969
8010
|
step.transitions.forEach((transition) => {
|
|
7970
8011
|
switch (transition.type) {
|
|
7971
8012
|
case "dom-click":
|
|
7972
8013
|
this.setupDOMClickTransition(transition);
|
|
7973
8014
|
break;
|
|
7974
8015
|
case "timeout":
|
|
7975
|
-
|
|
8016
|
+
if (!skipTimeouts) {
|
|
8017
|
+
this.setupTimeoutTransition(transition, triggerImmediately);
|
|
8018
|
+
}
|
|
7976
8019
|
break;
|
|
7977
8020
|
case "url-path":
|
|
7978
8021
|
this.setupURLPathTransition(transition);
|
|
@@ -8078,7 +8121,7 @@ class TransitionManager {
|
|
|
8078
8121
|
let timeoutId = null;
|
|
8079
8122
|
if (triggerImmediately) {
|
|
8080
8123
|
this.triggerTransition(nextStepId);
|
|
8081
|
-
} else
|
|
8124
|
+
} else {
|
|
8082
8125
|
timeoutId = window.setTimeout(() => {
|
|
8083
8126
|
this.triggerTransition(nextStepId);
|
|
8084
8127
|
}, timeout);
|
|
@@ -9382,11 +9425,16 @@ class PlaylistLoader {
|
|
|
9382
9425
|
if (progressData.status === "completed") {
|
|
9383
9426
|
startStepId = manifest.startStep;
|
|
9384
9427
|
} else {
|
|
9385
|
-
const
|
|
9386
|
-
if (
|
|
9387
|
-
|
|
9388
|
-
|
|
9389
|
-
|
|
9428
|
+
const { isValid, ageMs } = isProgressRecent(progressData);
|
|
9429
|
+
if (!isValid) {
|
|
9430
|
+
startStepId = manifest.startStep;
|
|
9431
|
+
} else {
|
|
9432
|
+
const lastStepId = progressData.currentStepId || progressData.lastStepId;
|
|
9433
|
+
if (lastStepId) {
|
|
9434
|
+
const savedStep = manifest.steps.find((step) => step.id === lastStepId);
|
|
9435
|
+
if (savedStep) {
|
|
9436
|
+
startStepId = lastStepId;
|
|
9437
|
+
}
|
|
9390
9438
|
}
|
|
9391
9439
|
}
|
|
9392
9440
|
}
|
|
@@ -10748,7 +10796,7 @@ const SaltfishPlayer$1 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.de
|
|
|
10748
10796
|
__proto__: null,
|
|
10749
10797
|
SaltfishPlayer
|
|
10750
10798
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
10751
|
-
const version = "0.2.
|
|
10799
|
+
const version = "0.2.74";
|
|
10752
10800
|
const packageJson = {
|
|
10753
10801
|
version
|
|
10754
10802
|
};
|