saltfish 0.3.27 → 0.3.29

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.
@@ -957,13 +957,6 @@ const STORAGE_KEYS = {
957
957
  SESSION: "saltfish_session",
958
958
  ANONYMOUS_USER: "saltfish_anonymous_user_data"
959
959
  };
960
- const TIMING$1 = {
961
- // 5 seconds
962
- STEP_TIMEOUT: 12e4,
963
- // Session persistence
964
- SESSION_EXPIRY: 30 * 60 * 1e3
965
- // 30 minutes in milliseconds
966
- };
967
960
  const API = {
968
961
  BASE_URL: "https://player.saltfish.ai",
969
962
  SHARE_BASE_URL: "https://studio-api.saltfish.ai/studio/flows2/share",
@@ -1514,6 +1507,14 @@ const useSaltfishStore = {
1514
1507
  subscribe: saltfishStore.subscribe,
1515
1508
  destroy: saltfishStore.destroy
1516
1509
  };
1510
+ function getSaltfishStore() {
1511
+ try {
1512
+ return useSaltfishStore.getState();
1513
+ } catch (error2) {
1514
+ const errorMessage = `[storeUtils] Failed to access Saltfish store: ${error2}`;
1515
+ throw new Error(errorMessage);
1516
+ }
1517
+ }
1517
1518
  const MAX_PROGRESS_AGE_MS = 6e3;
1518
1519
  function parseProgressTimestamp(progressData) {
1519
1520
  if (!progressData) {
@@ -1695,7 +1696,7 @@ class ErrorHandler {
1695
1696
  */
1696
1697
  static updateStore(error2) {
1697
1698
  try {
1698
- const store = useSaltfishStore.getState();
1699
+ const store = getSaltfishStore();
1699
1700
  store.setError(error2);
1700
1701
  } catch (storeError) {
1701
1702
  console.error("Failed to update store with error:", storeError);
@@ -1707,7 +1708,7 @@ class ErrorHandler {
1707
1708
  static triggerErrorEvent(error2, context, errorType) {
1708
1709
  var _a, _b;
1709
1710
  try {
1710
- const store = useSaltfishStore.getState();
1711
+ const store = getSaltfishStore();
1711
1712
  if (typeof window !== "undefined" && window._saltfishPlayer) {
1712
1713
  const player = window._saltfishPlayer;
1713
1714
  if (player && player.eventManager) {
@@ -1936,7 +1937,7 @@ class PlayerInitializationService {
1936
1937
  // Default to true if not specified
1937
1938
  };
1938
1939
  this.lastConfig = updatedConfig;
1939
- const store = useSaltfishStore.getState();
1940
+ const store = getSaltfishStore();
1940
1941
  store.initialize(updatedConfig);
1941
1942
  this.managers.analyticsManager.initialize(config, this.managers.sessionManager.getSessionId());
1942
1943
  if (data.isAdmin && store.setIsAdmin) {
@@ -1986,7 +1987,7 @@ class PlayerInitializationService {
1986
1987
  async fetchUserData(userId, userData) {
1987
1988
  var _a;
1988
1989
  try {
1989
- const store = useSaltfishStore.getState();
1990
+ const store = getSaltfishStore();
1990
1991
  if (!((_a = store.config) == null ? void 0 : _a.token)) {
1991
1992
  ErrorHandler.handleWarning(
1992
1993
  "Cannot fetch user data: Token not available",
@@ -2110,7 +2111,7 @@ class PlayerInitializationService {
2110
2111
  log("[PlayerInitializationService.loadAnonymousUserData] Loaded existing anonymous user data:", anonymousUserData);
2111
2112
  }
2112
2113
  this.managers.storageManager.setAnonymousUserData(anonymousUserData);
2113
- const store = useSaltfishStore.getState();
2114
+ const store = getSaltfishStore();
2114
2115
  store.setUserData({
2115
2116
  watchedPlaylists: anonymousUserData.watchedPlaylists || {},
2116
2117
  language: userData == null ? void 0 : userData.language
@@ -2165,7 +2166,7 @@ class PlayerInitializationService {
2165
2166
  if (!watchedPlaylists) {
2166
2167
  return false;
2167
2168
  }
2168
- const store = useSaltfishStore.getState();
2169
+ const store = getSaltfishStore();
2169
2170
  const currentManifestId = (_a = store.manifest) == null ? void 0 : _a.id;
2170
2171
  const currentState = store.currentState;
2171
2172
  if (currentManifestId && currentState !== "idle" && currentState !== "error") {
@@ -2291,7 +2292,7 @@ class UserManagementService {
2291
2292
  log(`UserManagementService: Processed language from userData: ${userData.language} -> ${processedLanguage}`);
2292
2293
  }
2293
2294
  this.lastUserIdentification = { userId, userData: processedUserData };
2294
- const store = useSaltfishStore.getState();
2295
+ const store = getSaltfishStore();
2295
2296
  store.identifyUser(userId, processedUserData);
2296
2297
  this.managers.analyticsManager.setUser({
2297
2298
  id: userId,
@@ -2326,7 +2327,7 @@ class UserManagementService {
2326
2327
  }
2327
2328
  const userId = this.playerInitializationService.getOrCreateAnonymousUserId();
2328
2329
  this.lastUserIdentification = { userId, userData: processedUserData };
2329
- const store = useSaltfishStore.getState();
2330
+ const store = getSaltfishStore();
2330
2331
  store.identifyUser(userId, { ...processedUserData, __isAnonymous: true });
2331
2332
  this.managers.analyticsManager.setUser({
2332
2333
  id: userId,
@@ -2340,7 +2341,7 @@ class UserManagementService {
2340
2341
  async recordABTestAttempt(playlistId) {
2341
2342
  var _a;
2342
2343
  try {
2343
- const store = useSaltfishStore.getState();
2344
+ const store = getSaltfishStore();
2344
2345
  const user = store.user;
2345
2346
  if (!user || !((_a = store.config) == null ? void 0 : _a.token)) {
2346
2347
  return;
@@ -2402,7 +2403,7 @@ class PlaylistValidator {
2402
2403
  async validatePlaylistStart(context) {
2403
2404
  const { playlistId, options, eventManager } = context;
2404
2405
  try {
2405
- const store = useSaltfishStore.getState();
2406
+ const store = getSaltfishStore();
2406
2407
  if (!store.config) {
2407
2408
  return {
2408
2409
  isValid: false,
@@ -2513,7 +2514,7 @@ class PlaylistValidator {
2513
2514
  */
2514
2515
  async validateTriggerConditions(playlistId, foundPlaylist, eventManager) {
2515
2516
  var _a, _b;
2516
- const store = useSaltfishStore.getState();
2517
+ const store = getSaltfishStore();
2517
2518
  if (!store.user) {
2518
2519
  ErrorHandler.handlePlaylistError(
2519
2520
  "User must be identified before starting auto-start playlist",
@@ -2529,7 +2530,7 @@ class PlaylistValidator {
2529
2530
  if (!store.userData) {
2530
2531
  await this.waitForUserData(eventManager);
2531
2532
  }
2532
- const currentStore = useSaltfishStore.getState();
2533
+ const currentStore = getSaltfishStore();
2533
2534
  const watchedPlaylists = ((_a = currentStore.userData) == null ? void 0 : _a.watchedPlaylists) || {};
2534
2535
  const hasTriggers = foundPlaylist.hasTriggers ?? foundPlaylist.autoStart ?? false;
2535
2536
  const playlistData = watchedPlaylists[playlistId];
@@ -2547,7 +2548,7 @@ class PlaylistValidator {
2547
2548
  */
2548
2549
  async validateOnceOptionConditions(playlistId, options, eventManager) {
2549
2550
  var _a;
2550
- const store = useSaltfishStore.getState();
2551
+ const store = getSaltfishStore();
2551
2552
  if (!store.user) {
2552
2553
  ErrorHandler.handlePlaylistError(
2553
2554
  "User must be identified before starting playlist with once option",
@@ -2563,7 +2564,7 @@ class PlaylistValidator {
2563
2564
  if (!store.userData) {
2564
2565
  await this.waitForUserData(eventManager);
2565
2566
  }
2566
- const currentStore = useSaltfishStore.getState();
2567
+ const currentStore = getSaltfishStore();
2567
2568
  const watchedPlaylists = ((_a = currentStore.userData) == null ? void 0 : _a.watchedPlaylists) || {};
2568
2569
  const playlistData = watchedPlaylists[playlistId];
2569
2570
  if (playlistData && (playlistData.status === "completed" || playlistData.status === "dismissed")) {
@@ -2634,7 +2635,7 @@ class PlaylistValidator {
2634
2635
  }, 5e3);
2635
2636
  const handler = () => {
2636
2637
  clearTimeout(timeout);
2637
- useSaltfishStore.getState();
2638
+ getSaltfishStore();
2638
2639
  resolve();
2639
2640
  };
2640
2641
  eventManager.on("userDataLoaded", handler);
@@ -2717,7 +2718,7 @@ class PlaylistOrchestrator {
2717
2718
  this.stateMachineActionHandler.registerStateMachineActions();
2718
2719
  }
2719
2720
  }
2720
- const store = useSaltfishStore.getState();
2721
+ const store = getSaltfishStore();
2721
2722
  if (!store.config) {
2722
2723
  const lastConfig = (_b = this.playerInitializationService) == null ? void 0 : _b.getLastConfig();
2723
2724
  if (!lastConfig) {
@@ -2819,7 +2820,7 @@ class PlaylistOrchestrator {
2819
2820
  this.managers.cursorManager.resetFirstAnimation();
2820
2821
  log(`[PlaylistOrchestrator.startPlaylist] Using validated manifest path: ${manifestPathToLoad}`);
2821
2822
  await this.managers.playlistManager.load(manifestPathToLoad, { ...finalOptions, persistence: playlistPersistence });
2822
- const updatedStore = useSaltfishStore.getState();
2823
+ const updatedStore = getSaltfishStore();
2823
2824
  if (updatedStore.manifest) {
2824
2825
  const manifestPersistence = finalOptions.persistence ?? updatedStore.manifest.isPersistent ?? true;
2825
2826
  const currentOptions = updatedStore.playlistOptions || {};
@@ -2861,7 +2862,7 @@ class PlaylistOrchestrator {
2861
2862
  info(`Playlist started: ${playlistId}${updatedStore.manifest ? ` (${updatedStore.manifest.name})` : ""}`);
2862
2863
  } catch (error2) {
2863
2864
  this.managers.uiManager.hideLoading();
2864
- const errorStore = useSaltfishStore.getState();
2865
+ const errorStore = getSaltfishStore();
2865
2866
  errorStore.sendStateMachineEvent({
2866
2867
  type: "ERROR",
2867
2868
  error: error2 instanceof Error ? error2 : new Error(String(error2))
@@ -2881,7 +2882,7 @@ class PlaylistOrchestrator {
2881
2882
  * Reset current playlist to initial state
2882
2883
  */
2883
2884
  resetPlaylist() {
2884
- const store = useSaltfishStore.getState();
2885
+ const store = getSaltfishStore();
2885
2886
  if (store.manifest) {
2886
2887
  store.goToStep(store.manifest.startStep);
2887
2888
  }
@@ -2890,7 +2891,7 @@ class PlaylistOrchestrator {
2890
2891
  * Check if the player is initialized
2891
2892
  */
2892
2893
  isInitialized() {
2893
- const store = useSaltfishStore.getState();
2894
+ const store = getSaltfishStore();
2894
2895
  return !!store.config;
2895
2896
  }
2896
2897
  /**
@@ -2923,7 +2924,7 @@ class StateMachineActionHandler {
2923
2924
  * Register all state machine actions with the store
2924
2925
  */
2925
2926
  registerStateMachineActions() {
2926
- const store = useSaltfishStore.getState();
2927
+ const store = getSaltfishStore();
2927
2928
  store.registerStateMachineActions({
2928
2929
  startVideoPlayback: (context) => {
2929
2930
  this.handleStartVideoPlayback(context);
@@ -2985,7 +2986,7 @@ class StateMachineActionHandler {
2985
2986
  */
2986
2987
  getVideoUrl(step) {
2987
2988
  var _a;
2988
- const store = useSaltfishStore.getState();
2989
+ const store = getSaltfishStore();
2989
2990
  const language = (_a = store.userData) == null ? void 0 : _a.language;
2990
2991
  let videoUrl;
2991
2992
  if (language && step.translations && step.translations[language]) {
@@ -3007,7 +3008,7 @@ class StateMachineActionHandler {
3007
3008
  */
3008
3009
  isUsingAudioFallback(step) {
3009
3010
  var _a;
3010
- const store = useSaltfishStore.getState();
3011
+ const store = getSaltfishStore();
3011
3012
  const language = (_a = store.userData) == null ? void 0 : _a.language;
3012
3013
  let videoUrl;
3013
3014
  if (language && step.translations && step.translations[language]) {
@@ -3021,7 +3022,7 @@ class StateMachineActionHandler {
3021
3022
  * Finds the URL of the next video in the playlist for preloading
3022
3023
  */
3023
3024
  findNextVideoUrl(currentStep) {
3024
- const store = useSaltfishStore.getState();
3025
+ const store = getSaltfishStore();
3025
3026
  if (!store.manifest || !currentStep) {
3026
3027
  return null;
3027
3028
  }
@@ -3116,7 +3117,7 @@ class StateMachineActionHandler {
3116
3117
  const videoUrl = this.getVideoUrl(currentStep);
3117
3118
  const isAudioFallback = this.isUsingAudioFallback(currentStep);
3118
3119
  if (isAudioFallback) {
3119
- const store = useSaltfishStore.getState();
3120
+ const store = getSaltfishStore();
3120
3121
  const manifest = store.manifest;
3121
3122
  const posterUrl = currentStep.gifUrl;
3122
3123
  const avatarThumbnailUrl = manifest == null ? void 0 : manifest.avatarThumbnailUrl;
@@ -3154,7 +3155,7 @@ class StateMachineActionHandler {
3154
3155
  }
3155
3156
  this.managers.videoManager.setCompletionPolicy(completionPolicy, () => {
3156
3157
  var _a;
3157
- const store = useSaltfishStore.getState();
3158
+ const store = getSaltfishStore();
3158
3159
  if (!hasSpecialTransitions) {
3159
3160
  log("StateMachineActionHandler: Setting up transitions after video ended");
3160
3161
  this.managers.transitionManager.setupTransitions(currentStep, true);
@@ -3177,7 +3178,7 @@ class StateMachineActionHandler {
3177
3178
  log(`StateMachineActionHandler: Video ended, setting up timeout transition to ${timeoutTransition.nextStep} with ${timeout}ms delay`);
3178
3179
  setTimeout(() => {
3179
3180
  var _a2;
3180
- const currentStore = useSaltfishStore.getState();
3181
+ const currentStore = getSaltfishStore();
3181
3182
  if (currentStore.currentStepId === currentStep.id && (currentStore.currentState === "waitingForInteraction" || currentStore.currentState === "playing")) {
3182
3183
  log(`StateMachineActionHandler: Timeout expired (${timeout}ms), transitioning to ${timeoutTransition.nextStep}`);
3183
3184
  (_a2 = currentStore.goToStep) == null ? void 0 : _a2.call(currentStore, timeoutTransition.nextStep);
@@ -3205,7 +3206,7 @@ class StateMachineActionHandler {
3205
3206
  log("StateMachineActionHandler: Starting async video load");
3206
3207
  const loadTranscriptForStep = () => {
3207
3208
  var _a, _b;
3208
- const store = useSaltfishStore.getState();
3209
+ const store = getSaltfishStore();
3209
3210
  const captionsEnabled = ((_a = store.manifest) == null ? void 0 : _a.captions) ?? true;
3210
3211
  const language = (_b = store.userData) == null ? void 0 : _b.language;
3211
3212
  let transcript = currentStep.transcript;
@@ -3250,7 +3251,7 @@ class StateMachineActionHandler {
3250
3251
  error2 instanceof Error ? error2 : new Error(`Failed to load video: ${error2}`),
3251
3252
  "video"
3252
3253
  );
3253
- const store = useSaltfishStore.getState();
3254
+ const store = getSaltfishStore();
3254
3255
  const errorObj = error2 instanceof Error ? error2 : new Error(`Failed to load video: ${error2}`);
3255
3256
  const enrichedError = error2;
3256
3257
  this.managers.eventManager.trigger("error", {
@@ -3289,7 +3290,7 @@ class StateMachineActionHandler {
3289
3290
  const isAudioFallback = this.isUsingAudioFallback(currentStep);
3290
3291
  this.managers.uiManager.showPlayer();
3291
3292
  if (isAudioFallback) {
3292
- const store = useSaltfishStore.getState();
3293
+ const store = getSaltfishStore();
3293
3294
  const manifest = store.manifest;
3294
3295
  const posterUrl = currentStep.gifUrl;
3295
3296
  const avatarThumbnailUrl = manifest == null ? void 0 : manifest.avatarThumbnailUrl;
@@ -3314,7 +3315,7 @@ class StateMachineActionHandler {
3314
3315
  }
3315
3316
  handleTrackPlaylistComplete() {
3316
3317
  var _a, _b;
3317
- const store = useSaltfishStore.getState();
3318
+ const store = getSaltfishStore();
3318
3319
  if (store.manifest && this.managers.eventManager) {
3319
3320
  const playlistId = store.manifest.id;
3320
3321
  this.managers.eventManager.trigger("playlistEnded", {
@@ -3338,7 +3339,7 @@ class StateMachineActionHandler {
3338
3339
  log(`StateMachineActionHandler: Handling error: ${(_a = context.error) == null ? void 0 : _a.message}`);
3339
3340
  if (context.error && this.managers.uiManager.getPlayerElement()) {
3340
3341
  this.managers.uiManager.showError(context.error, "player");
3341
- const store = useSaltfishStore.getState();
3342
+ const store = getSaltfishStore();
3342
3343
  this.managers.eventManager.trigger("error", {
3343
3344
  timestamp: Date.now(),
3344
3345
  playlistId: ((_b = store.manifest) == null ? void 0 : _b.id) || void 0,
@@ -3378,7 +3379,7 @@ class StateMachineActionHandler {
3378
3379
  this.managers.uiManager.disablePlayButtonProminent();
3379
3380
  }
3380
3381
  handleTriggerPlaylistDismissed() {
3381
- const store = useSaltfishStore.getState();
3382
+ const store = getSaltfishStore();
3382
3383
  if (store.manifest && this.managers.eventManager) {
3383
3384
  this.managers.eventManager.trigger("playlistDismissed", {
3384
3385
  timestamp: Date.now(),
@@ -3705,7 +3706,7 @@ const _ManagerOrchestrator = class _ManagerOrchestrator {
3705
3706
  if (!this.isInitialized) {
3706
3707
  return;
3707
3708
  }
3708
- const store = useSaltfishStore.getState();
3709
+ const store = getSaltfishStore();
3709
3710
  if (store.currentState === _ManagerOrchestrator.prevState.currentState && store.currentStepId === _ManagerOrchestrator.prevState.currentStepId && store.isMinimized === _ManagerOrchestrator.prevState.isMinimized) {
3710
3711
  return;
3711
3712
  }
@@ -3793,7 +3794,7 @@ const _ManagerOrchestrator = class _ManagerOrchestrator {
3793
3794
  return;
3794
3795
  }
3795
3796
  try {
3796
- const store = useSaltfishStore.getState();
3797
+ const store = getSaltfishStore();
3797
3798
  log("ManagerOrchestrator: Current state before playlist cleanup:", {
3798
3799
  currentState: store.currentState,
3799
3800
  currentStepId: store.currentStepId,
@@ -3832,7 +3833,7 @@ const _ManagerOrchestrator = class _ManagerOrchestrator {
3832
3833
  return;
3833
3834
  }
3834
3835
  try {
3835
- const store = useSaltfishStore.getState();
3836
+ const store = getSaltfishStore();
3836
3837
  log("ManagerOrchestrator: Current state before destroying:", {
3837
3838
  currentState: store.currentState,
3838
3839
  currentStepId: store.currentStepId,
@@ -3871,7 +3872,7 @@ const _ManagerOrchestrator = class _ManagerOrchestrator {
3871
3872
  try {
3872
3873
  log("ManagerOrchestrator: Attempting emergency cleanup after error");
3873
3874
  this.isInitialized = false;
3874
- const store = useSaltfishStore.getState();
3875
+ const store = getSaltfishStore();
3875
3876
  store.reset();
3876
3877
  log("ManagerOrchestrator: Emergency cleanup completed");
3877
3878
  } catch (cleanupError) {
@@ -4738,7 +4739,7 @@ class MobilePlaybackHandler extends DevicePlaybackHandler {
4738
4739
  element.style.setProperty("min-height", config.buttonMinSize.height);
4739
4740
  }
4740
4741
  async handlePlayAttempt(video, hasUserInteracted) {
4741
- const store = useSaltfishStore.getState();
4742
+ const store = getSaltfishStore();
4742
4743
  const userWantsMuted = store.isMuted;
4743
4744
  video.muted = userWantsMuted;
4744
4745
  video.loop = false;
@@ -4822,7 +4823,7 @@ class DesktopPlaybackHandler extends DevicePlaybackHandler {
4822
4823
  configureControlElement(_element) {
4823
4824
  }
4824
4825
  async handlePlayAttempt(video, _hasUserInteracted) {
4825
- const store = useSaltfishStore.getState();
4826
+ const store = getSaltfishStore();
4826
4827
  const userWantsMuted = store.isMuted;
4827
4828
  video.muted = userWantsMuted;
4828
4829
  video.loop = false;
@@ -5130,7 +5131,7 @@ class VideoControlsUI {
5130
5131
  * Sets the muted state
5131
5132
  */
5132
5133
  setMuted(muted) {
5133
- const store = useSaltfishStore.getState();
5134
+ const store = getSaltfishStore();
5134
5135
  store.setMuted(muted);
5135
5136
  this.updateMuteButtonIcon();
5136
5137
  }
@@ -5138,7 +5139,7 @@ class VideoControlsUI {
5138
5139
  * Toggles the muted state
5139
5140
  */
5140
5141
  toggleMute() {
5141
- const store = useSaltfishStore.getState();
5142
+ const store = getSaltfishStore();
5142
5143
  const newMutedState = !store.isMuted;
5143
5144
  this.setMuted(newMutedState);
5144
5145
  this.callbacks.onMuteToggle();
@@ -5147,7 +5148,7 @@ class VideoControlsUI {
5147
5148
  * Gets the current muted state
5148
5149
  */
5149
5150
  getMuted() {
5150
- const store = useSaltfishStore.getState();
5151
+ const store = getSaltfishStore();
5151
5152
  return store.isMuted;
5152
5153
  }
5153
5154
  /**
@@ -5155,7 +5156,7 @@ class VideoControlsUI {
5155
5156
  */
5156
5157
  updateMuteButtonIcon() {
5157
5158
  if (!this.muteButton) return;
5158
- const store = useSaltfishStore.getState();
5159
+ const store = getSaltfishStore();
5159
5160
  const isMuted = store.isMuted;
5160
5161
  if (isMuted) {
5161
5162
  this.muteButton.innerHTML = `
@@ -5622,7 +5623,7 @@ class VideoManager {
5622
5623
  if (video !== activeVideo) {
5623
5624
  return;
5624
5625
  }
5625
- const store = useSaltfishStore.getState();
5626
+ const store = getSaltfishStore();
5626
5627
  if (store.currentState === "autoplayBlocked" || store.currentState === "idleMode") {
5627
5628
  store.currentState === "autoplayBlocked" ? "autoplay blocked" : "idle";
5628
5629
  return;
@@ -5713,7 +5714,7 @@ class VideoManager {
5713
5714
  this.nextVideo.crossOrigin = "anonymous";
5714
5715
  this.deviceHandler.configureVideoElement(this.nextVideo);
5715
5716
  this.container.appendChild(this.nextVideo);
5716
- const store = useSaltfishStore.getState();
5717
+ const store = getSaltfishStore();
5717
5718
  if (store.isMuted) {
5718
5719
  this.currentVideo.muted = true;
5719
5720
  this.nextVideo.muted = true;
@@ -5771,7 +5772,7 @@ class VideoManager {
5771
5772
  return;
5772
5773
  }
5773
5774
  activeVideo.pause();
5774
- const store = useSaltfishStore.getState();
5775
+ const store = getSaltfishStore();
5775
5776
  inactiveVideo.muted = store.isMuted;
5776
5777
  activeVideo.classList.add("sf-hidden");
5777
5778
  inactiveVideo.classList.remove("sf-hidden");
@@ -5795,13 +5796,13 @@ class VideoManager {
5795
5796
  if (this.controls) {
5796
5797
  this.controls.reset90PercentTrigger();
5797
5798
  }
5798
- const store = useSaltfishStore.getState();
5799
+ const store = getSaltfishStore();
5799
5800
  activeVideo.muted = store.isMuted;
5800
5801
  try {
5801
5802
  if (this.controls) {
5802
5803
  this.controls.reset();
5803
5804
  }
5804
- const store2 = useSaltfishStore.getState();
5805
+ const store2 = getSaltfishStore();
5805
5806
  const isPersistenceEnabled = ((_a = store2.playlistOptions) == null ? void 0 : _a.persistence) ?? true;
5806
5807
  if (this.currentVideoUrl === url && activeVideo.src && (activeVideo.src === url || activeVideo.src.endsWith(url))) {
5807
5808
  if (isPersistenceEnabled) {
@@ -5940,7 +5941,7 @@ class VideoManager {
5940
5941
  inactiveVideo.src = url;
5941
5942
  inactiveVideo.load();
5942
5943
  inactiveVideo.preload = "auto";
5943
- const store = useSaltfishStore.getState();
5944
+ const store = getSaltfishStore();
5944
5945
  inactiveVideo.muted = store.isMuted;
5945
5946
  } else {
5946
5947
  fetch(url).then((response) => {
@@ -5969,7 +5970,7 @@ class VideoManager {
5969
5970
  if (activeVideo.ended) {
5970
5971
  activeVideo.currentTime = 0;
5971
5972
  }
5972
- const store = useSaltfishStore.getState();
5973
+ const store = getSaltfishStore();
5973
5974
  const isPersistenceEnabled = ((_a = store.playlistOptions) == null ? void 0 : _a.persistence) ?? true;
5974
5975
  if (isPersistenceEnabled && this.currentVideoUrl) {
5975
5976
  const savedPosition = this.playbackPositions.get(this.currentVideoUrl);
@@ -6017,7 +6018,7 @@ class VideoManager {
6017
6018
  }
6018
6019
  }).catch(() => {
6019
6020
  console.warn("VideoManager: Autoplay handler threw error - browser has strict autoplay policy");
6020
- const store2 = useSaltfishStore.getState();
6021
+ const store2 = getSaltfishStore();
6021
6022
  store2.setAutoplayFallback();
6022
6023
  });
6023
6024
  }
@@ -6432,14 +6433,34 @@ const ANALYTICS = {
6432
6433
  FLUSH_INTERVAL_MS: 3e4
6433
6434
  };
6434
6435
  const TIMING = {
6436
+ // Polling and updates
6437
+ /** Video progress polling interval (50ms) */
6438
+ VIDEO_PROGRESS_POLL_INTERVAL: 50,
6439
+ /** Cursor position update throttle interval (100ms) */
6440
+ CURSOR_UPDATE_THROTTLE: 100,
6441
+ /** Delay for state processing operations (100ms) */
6442
+ STATE_PROCESSING_DELAY_MS: 100,
6443
+ // Analytics
6444
+ /** Analytics event flush interval (30 seconds) */
6445
+ ANALYTICS_FLUSH_INTERVAL: 3e4,
6446
+ // Timeouts
6447
+ /** User data loading timeout (5 seconds) */
6448
+ USER_DATA_TIMEOUT: 5e3,
6449
+ /** Step timeout - player will be destroyed if user stays on same step (120 seconds) */
6450
+ STEP_TIMEOUT: 12e4,
6451
+ /** Retry delay for failed operations (0.5 seconds) */
6452
+ RETRY_DELAY_MS: 500,
6453
+ // DOM and cursor operations
6435
6454
  /** Delay for DOM stabilization before cursor operations (0.5 seconds) */
6436
6455
  DOM_STABILIZATION_DELAY_MS: 500,
6437
- /** Delay for state processing operations (100 milliseconds) */
6438
- STATE_PROCESSING_DELAY_MS: 100,
6456
+ /** Default cursor animation distance in pixels */
6457
+ CURSOR_DEFAULT_DISTANCE: 100,
6458
+ // URL monitoring
6439
6459
  /** Interval for checking URL path changes (5 seconds) */
6440
6460
  URL_PATH_CHECK_INTERVAL_MS: 5e3,
6441
- /** Retry delay for failed operations (0.5 seconds) */
6442
- RETRY_DELAY_MS: 500
6461
+ // Session persistence
6462
+ /** Session expiry time (30 minutes) */
6463
+ SESSION_EXPIRY: 30 * 60 * 1e3
6443
6464
  };
6444
6465
  const THRESHOLDS = {
6445
6466
  /** Minimum scroll distance in pixels to trigger scroll events */
@@ -7817,7 +7838,7 @@ class InteractionManager {
7817
7838
  if (needsScrolling && this.buttonContainer) {
7818
7839
  this.setupScrollIndicator(this.buttonContainer);
7819
7840
  }
7820
- const store = useSaltfishStore.getState();
7841
+ const store = getSaltfishStore();
7821
7842
  if (store.isMinimized) {
7822
7843
  this.buttonContainer.classList.add("sf-hidden");
7823
7844
  }
@@ -7896,7 +7917,7 @@ class InteractionManager {
7896
7917
  if (!this.buttonContainer || this.buttons.length === 0) {
7897
7918
  return;
7898
7919
  }
7899
- const store = useSaltfishStore.getState();
7920
+ const store = getSaltfishStore();
7900
7921
  if (store.isMinimized) {
7901
7922
  this.buttonContainer.classList.add("sf-hidden");
7902
7923
  if (this.scrollIndicator) {
@@ -7967,7 +7988,7 @@ class InteractionManager {
7967
7988
  log(`InteractionManager: Button click detected on button "${buttonConfig.id}"`);
7968
7989
  event.preventDefault();
7969
7990
  event.stopPropagation();
7970
- const store = useSaltfishStore.getState();
7991
+ const store = getSaltfishStore();
7971
7992
  switch (buttonConfig.action.type) {
7972
7993
  case "next":
7973
7994
  store.play();
@@ -7976,7 +7997,7 @@ class InteractionManager {
7976
7997
  if (buttonConfig.action.url) {
7977
7998
  log(`InteractionManager: Goto button with URL redirect - updating to step "${buttonConfig.action.target}" then redirecting to "${buttonConfig.action.url}"`);
7978
7999
  await this.flushAnalytics();
7979
- const currentStore = useSaltfishStore.getState();
8000
+ const currentStore = getSaltfishStore();
7980
8001
  if (currentStore.manifest) {
7981
8002
  useSaltfishStore.setState((state) => {
7982
8003
  state.currentStepId = buttonConfig.action.target;
@@ -8019,7 +8040,7 @@ class InteractionManager {
8019
8040
  const playlistPersistence = ((_d = currentStore.playlistOptions) == null ? void 0 : _d.persistence) ?? true;
8020
8041
  if (playlistPersistence) {
8021
8042
  const userId = (_e = currentStore.user) == null ? void 0 : _e.id;
8022
- const updatedStore = useSaltfishStore.getState();
8043
+ const updatedStore = getSaltfishStore();
8023
8044
  this.storageManager.setProgress(updatedStore.progress, userId);
8024
8045
  log(`InteractionManager: Saved progress for step ${buttonConfig.action.target} before URL redirect`);
8025
8046
  if ((_f = currentStore.user) == null ? void 0 : _f.__isAnonymous) {
@@ -8116,7 +8137,7 @@ class InteractionManager {
8116
8137
  log(`InteractionManager: Set input value to "${interaction.value}"`);
8117
8138
  }
8118
8139
  }
8119
- const store = useSaltfishStore.getState();
8140
+ const store = getSaltfishStore();
8120
8141
  if (store.manifest) {
8121
8142
  const analyticsData = {
8122
8143
  selector: interaction.selector,
@@ -8185,13 +8206,6 @@ class InteractionManager {
8185
8206
  this.container = null;
8186
8207
  }
8187
8208
  }
8188
- function getSaltfishStore() {
8189
- try {
8190
- return useSaltfishStore.getState();
8191
- } catch (error2) {
8192
- return null;
8193
- }
8194
- }
8195
8209
  class AnalyticsManager {
8196
8210
  // Default to enabled
8197
8211
  /**
@@ -8569,7 +8583,7 @@ class SessionManager {
8569
8583
  const sessionData = this.storageManager.getSession();
8570
8584
  if (sessionData) {
8571
8585
  const now = Date.now();
8572
- if (now - sessionData.lastActivity < TIMING$1.SESSION_EXPIRY) {
8586
+ if (now - sessionData.lastActivity < TIMING.SESSION_EXPIRY) {
8573
8587
  log(`SessionManager: Using existing session: ${sessionData.sessionId}`);
8574
8588
  this.updateSessionActivity(sessionData.sessionId);
8575
8589
  return sessionData.sessionId;
@@ -8895,7 +8909,7 @@ class TransitionManager {
8895
8909
  return;
8896
8910
  }
8897
8911
  retries++;
8898
- const currentStore = useSaltfishStore.getState();
8912
+ const currentStore = getSaltfishStore();
8899
8913
  if (currentStore.currentState === "waitingForInteraction" || currentStore.currentState === "playing") {
8900
8914
  log(`TransitionManager: State now compatible (${currentStore.currentState}), triggering transition to '${nextStepId}'`);
8901
8915
  this.triggerTransition(nextStepId);
@@ -8992,7 +9006,7 @@ class TransitionManager {
8992
9006
  * @returns true if validation passes or no requirement exists, false if validation fails
8993
9007
  */
8994
9008
  validateCurrentStepUrl() {
8995
- const store = useSaltfishStore.getState();
9009
+ const store = getSaltfishStore();
8996
9010
  const manifest = store.manifest;
8997
9011
  const currentStepId = store.currentStepId;
8998
9012
  if (!manifest || !currentStepId) {
@@ -9014,7 +9028,7 @@ class TransitionManager {
9014
9028
  */
9015
9029
  triggerTransition(nextStepId) {
9016
9030
  var _a;
9017
- const store = useSaltfishStore.getState();
9031
+ const store = getSaltfishStore();
9018
9032
  const currentState = store.currentState;
9019
9033
  store.currentStepId;
9020
9034
  const isMinimized = store.isMinimized;
@@ -9037,7 +9051,7 @@ class TransitionManager {
9037
9051
  * @returns Promise<boolean> - True if transition was successful, false otherwise
9038
9052
  */
9039
9053
  async triggerTransitionWithProgress(nextStepId) {
9040
- const store = useSaltfishStore.getState();
9054
+ const store = getSaltfishStore();
9041
9055
  const currentState = store.currentState;
9042
9056
  store.currentStepId;
9043
9057
  const isMinimized = store.isMinimized;
@@ -9366,7 +9380,7 @@ class TriggerManager {
9366
9380
  if (this.triggeredPlaylistsSet.has(playlistId)) {
9367
9381
  return;
9368
9382
  }
9369
- const store = useSaltfishStore.getState();
9383
+ const store = getSaltfishStore();
9370
9384
  if (!store.user) {
9371
9385
  return;
9372
9386
  }
@@ -9813,7 +9827,7 @@ class ABTestManager {
9813
9827
  * @param abTests - A/B test configurations from validate-token response
9814
9828
  */
9815
9829
  initializeTests(abTests) {
9816
- const store = useSaltfishStore.getState();
9830
+ const store = getSaltfishStore();
9817
9831
  store.setABTests(abTests);
9818
9832
  }
9819
9833
  /**
@@ -9825,7 +9839,7 @@ class ABTestManager {
9825
9839
  */
9826
9840
  assignUserToTests(userId, existingAssignments, userListAssignments) {
9827
9841
  var _a, _b;
9828
- const store = useSaltfishStore.getState();
9842
+ const store = getSaltfishStore();
9829
9843
  const abTests = store.abTests || [];
9830
9844
  const assignments = { ...existingAssignments };
9831
9845
  for (const test of abTests) {
@@ -9876,7 +9890,7 @@ class ABTestManager {
9876
9890
  * @returns Filtered playlists based on A/B test assignments
9877
9891
  */
9878
9892
  getFilteredPlaylists(allPlaylists) {
9879
- const store = useSaltfishStore.getState();
9893
+ const store = getSaltfishStore();
9880
9894
  const abTests = store.abTests || [];
9881
9895
  const assignments = store.abTestAssignments || {};
9882
9896
  if (abTests.length === 0) {
@@ -9902,7 +9916,7 @@ class ABTestManager {
9902
9916
  */
9903
9917
  trackTestParticipation(playlistId) {
9904
9918
  var _a;
9905
- const store = useSaltfishStore.getState();
9919
+ const store = getSaltfishStore();
9906
9920
  const abTests = store.abTests || [];
9907
9921
  const assignments = store.abTestAssignments || {};
9908
9922
  const test = abTests.find((t) => t.playlistId === playlistId);
@@ -9931,7 +9945,7 @@ class ABTestManager {
9931
9945
  * @returns A/B test assignments that should be stored in backend
9932
9946
  */
9933
9947
  getAssignmentsForBackend() {
9934
- const store = useSaltfishStore.getState();
9948
+ const store = getSaltfishStore();
9935
9949
  return store.abTestAssignments || {};
9936
9950
  }
9937
9951
  /**
@@ -9940,7 +9954,7 @@ class ABTestManager {
9940
9954
  * @returns true if playlist is available based on A/B test assignments
9941
9955
  */
9942
9956
  isPlaylistAvailable(playlistId) {
9943
- const store = useSaltfishStore.getState();
9957
+ const store = getSaltfishStore();
9944
9958
  const abTests = store.abTests || [];
9945
9959
  const assignments = store.abTestAssignments || {};
9946
9960
  const test = abTests.find((t) => t.playlistId === playlistId);
@@ -9955,7 +9969,7 @@ class ABTestManager {
9955
9969
  * @returns Array of active test information
9956
9970
  */
9957
9971
  getActiveTestInfo() {
9958
- const store = useSaltfishStore.getState();
9972
+ const store = getSaltfishStore();
9959
9973
  const abTests = store.abTests || [];
9960
9974
  const assignments = store.abTestAssignments || {};
9961
9975
  return abTests.map((test) => {
@@ -10240,9 +10254,6 @@ class PlaylistManager {
10240
10254
  this.isUpdatingWatchedPlaylists = true;
10241
10255
  try {
10242
10256
  const store = getSaltfishStore();
10243
- if (!store) {
10244
- return;
10245
- }
10246
10257
  const currentUserData = store.userData || {};
10247
10258
  const currentWatchedPlaylists = currentUserData.watchedPlaylists || {};
10248
10259
  const updatedPlaylistData = {
@@ -10382,10 +10393,10 @@ class MinimizeButton {
10382
10393
  `;
10383
10394
  this.button.addEventListener("click", this.handleClick.bind(this));
10384
10395
  this.playerElement.appendChild(this.button);
10385
- this.updateVisibility(useSaltfishStore.getState().isMinimized);
10396
+ this.updateVisibility(getSaltfishStore().isMinimized);
10386
10397
  }
10387
10398
  handleClick() {
10388
- const store = useSaltfishStore.getState();
10399
+ const store = getSaltfishStore();
10389
10400
  const isMinimized = !store.isMinimized;
10390
10401
  if (isMinimized) {
10391
10402
  store.minimize();
@@ -10448,7 +10459,7 @@ class PlayPauseButton {
10448
10459
  if (event) {
10449
10460
  event.stopPropagation();
10450
10461
  }
10451
- const store = useSaltfishStore.getState();
10462
+ const store = getSaltfishStore();
10452
10463
  if (store.currentState === "autoplayBlocked") {
10453
10464
  if (this.videoManager) {
10454
10465
  this.videoManager.markUserInteraction();
@@ -10499,11 +10510,11 @@ class ExitButton {
10499
10510
  `;
10500
10511
  this.button.addEventListener("click", this.handleClick.bind(this));
10501
10512
  this.playerElement.appendChild(this.button);
10502
- this.updateVisibility(useSaltfishStore.getState().isMinimized);
10513
+ this.updateVisibility(getSaltfishStore().isMinimized);
10503
10514
  }
10504
10515
  handleClick(e) {
10505
10516
  e.stopPropagation();
10506
- const store = useSaltfishStore.getState();
10517
+ const store = getSaltfishStore();
10507
10518
  store.sendStateMachineEvent({ type: "EXIT" });
10508
10519
  }
10509
10520
  updateVisibility(isMinimized) {
@@ -10747,7 +10758,7 @@ class UIManager {
10747
10758
  cursorManager.create();
10748
10759
  interactionManager.create(this.playerElement);
10749
10760
  this.initializeButtonManagement();
10750
- const store = useSaltfishStore.getState();
10761
+ const store = getSaltfishStore();
10751
10762
  this.handleMinimizeStateChange(store.isMinimized);
10752
10763
  }
10753
10764
  /**
@@ -10758,7 +10769,7 @@ class UIManager {
10758
10769
  const videoContainer = (_a = this.playerElement) == null ? void 0 : _a.querySelector(".sf-video-container");
10759
10770
  if (videoContainer) {
10760
10771
  videoContainer.addEventListener("click", (event) => {
10761
- const store = useSaltfishStore.getState();
10772
+ const store = getSaltfishStore();
10762
10773
  if (store.isMinimized) {
10763
10774
  event.stopPropagation();
10764
10775
  this.handleMinimizeClick();
@@ -10787,7 +10798,7 @@ class UIManager {
10787
10798
  });
10788
10799
  return;
10789
10800
  }
10790
- const store = useSaltfishStore.getState();
10801
+ const store = getSaltfishStore();
10791
10802
  let positionToUse = ((_a = store.playlistOptions) == null ? void 0 : _a.position) || "bottom-right";
10792
10803
  if (store.currentStepId && store.manifest) {
10793
10804
  const currentStep = store.manifest.steps.find((step) => step.id === store.currentStepId);
@@ -10818,7 +10829,7 @@ class UIManager {
10818
10829
  if (!this.playerElement) {
10819
10830
  return;
10820
10831
  }
10821
- const store = useSaltfishStore.getState();
10832
+ const store = getSaltfishStore();
10822
10833
  const isMinimized = !store.isMinimized;
10823
10834
  if (isMinimized) {
10824
10835
  store.minimize();
@@ -10960,7 +10971,7 @@ class UIManager {
10960
10971
  */
10961
10972
  createSaltfishLogo(parentElement) {
10962
10973
  var _a;
10963
- const store = useSaltfishStore.getState();
10974
+ const store = getSaltfishStore();
10964
10975
  if (((_a = store.config) == null ? void 0 : _a.showLogo) === false) {
10965
10976
  return;
10966
10977
  }
@@ -10977,7 +10988,7 @@ class UIManager {
10977
10988
  logoContainer.addEventListener("click", (event) => {
10978
10989
  var _a2;
10979
10990
  event.stopPropagation();
10980
- const currentStore = useSaltfishStore.getState();
10991
+ const currentStore = getSaltfishStore();
10981
10992
  if (currentStore.currentState === "playing") {
10982
10993
  currentStore.pause();
10983
10994
  }
@@ -11076,7 +11087,7 @@ class UIManager {
11076
11087
  var _a;
11077
11088
  e.stopPropagation();
11078
11089
  e.preventDefault();
11079
- const store = useSaltfishStore.getState();
11090
+ const store = getSaltfishStore();
11080
11091
  if (store.currentState === "autoplayBlocked" || store.currentState === "idleMode") {
11081
11092
  store.currentState === "autoplayBlocked" ? "autoplay fallback" : "idle";
11082
11093
  if (this.videoManager) {
@@ -11116,7 +11127,7 @@ class UIManager {
11116
11127
  return;
11117
11128
  }
11118
11129
  this.hideCompactLabel();
11119
- const store = useSaltfishStore.getState();
11130
+ const store = getSaltfishStore();
11120
11131
  let positionToUse = ((_a = store.playlistOptions) == null ? void 0 : _a.position) || "bottom-right";
11121
11132
  if (store.currentStepId && store.manifest) {
11122
11133
  const currentStep = store.manifest.steps.find((step) => step.id === store.currentStepId);
@@ -11135,7 +11146,7 @@ class UIManager {
11135
11146
  var _a2;
11136
11147
  e.stopPropagation();
11137
11148
  e.preventDefault();
11138
- const currentStore = useSaltfishStore.getState();
11149
+ const currentStore = getSaltfishStore();
11139
11150
  if (currentStore.currentState === "autoplayBlocked" || currentStore.currentState === "idleMode") {
11140
11151
  currentStore.currentState === "autoplayBlocked" ? "autoplay fallback" : "idle";
11141
11152
  if (this.videoManager) {
@@ -11343,7 +11354,7 @@ const _StepTimeoutManager = class _StepTimeoutManager {
11343
11354
  this.destroyCallback = null;
11344
11355
  }
11345
11356
  };
11346
- __publicField(_StepTimeoutManager, "STEP_TIMEOUT_MS", TIMING$1.STEP_TIMEOUT);
11357
+ __publicField(_StepTimeoutManager, "STEP_TIMEOUT_MS", TIMING.STEP_TIMEOUT);
11347
11358
  let StepTimeoutManager = _StepTimeoutManager;
11348
11359
  class ManagerFactory {
11349
11360
  /**
@@ -11601,7 +11612,7 @@ const SaltfishPlayer$1 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.de
11601
11612
  __proto__: null,
11602
11613
  SaltfishPlayer
11603
11614
  }, Symbol.toStringTag, { value: "Module" }));
11604
- const version = "0.3.27";
11615
+ const version = "0.3.29";
11605
11616
  const packageJson = {
11606
11617
  version
11607
11618
  };