saltfish 0.3.61 → 0.3.63
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 +14 -0
- package/dist/core/services/PlayerInitializationService.d.ts.map +1 -1
- package/dist/loaders/PlaylistLoader.d.ts +15 -0
- package/dist/loaders/PlaylistLoader.d.ts.map +1 -1
- package/dist/managers/StorageManager.d.ts +17 -1
- package/dist/managers/StorageManager.d.ts.map +1 -1
- package/dist/managers/TransitionManager.d.ts +19 -0
- 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 +243 -42
- package/dist/saltfish-playlist-player.umd.js +1 -1
- package/dist/types/index.d.ts +12 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/utils/constants.d.ts +2 -0
- package/dist/utils/constants.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -955,7 +955,8 @@ const playerStateMachineConfig = {
|
|
|
955
955
|
const STORAGE_KEYS = {
|
|
956
956
|
PROGRESS: "saltfish_progress",
|
|
957
957
|
SESSION: "saltfish_session",
|
|
958
|
-
ANONYMOUS_USER: "saltfish_anonymous_user_data"
|
|
958
|
+
ANONYMOUS_USER: "saltfish_anonymous_user_data",
|
|
959
|
+
PENDING_NAVIGATION: "saltfish_pending_navigation"
|
|
959
960
|
};
|
|
960
961
|
const API = {
|
|
961
962
|
BASE_URL: "https://player.saltfish.ai",
|
|
@@ -1155,6 +1156,32 @@ const _StorageManager = class _StorageManager {
|
|
|
1155
1156
|
this.safeClearItem(STORAGE_KEYS.ANONYMOUS_USER);
|
|
1156
1157
|
}
|
|
1157
1158
|
// =============================================================================
|
|
1159
|
+
// Pending Navigation Methods (Cross-page URL transitions)
|
|
1160
|
+
// =============================================================================
|
|
1161
|
+
/**
|
|
1162
|
+
* Get pending navigation data for cross-page URL transitions
|
|
1163
|
+
* Used when a step has a url-path transition and user navigates causing hard refresh
|
|
1164
|
+
*/
|
|
1165
|
+
getPendingNavigation() {
|
|
1166
|
+
return this.safeGetItem(STORAGE_KEYS.PENDING_NAVIGATION);
|
|
1167
|
+
}
|
|
1168
|
+
/**
|
|
1169
|
+
* Set pending navigation data
|
|
1170
|
+
* Called when setting up a url-path transition to enable resuming after hard refresh
|
|
1171
|
+
* @param data - The pending navigation data to save
|
|
1172
|
+
*/
|
|
1173
|
+
setPendingNavigation(data) {
|
|
1174
|
+
log(`[StorageManager] Saving pending navigation to step ${data.nextStepId} for pattern ${data.urlPattern}`);
|
|
1175
|
+
return this.safeSetItem(STORAGE_KEYS.PENDING_NAVIGATION, data);
|
|
1176
|
+
}
|
|
1177
|
+
/**
|
|
1178
|
+
* Clear pending navigation data
|
|
1179
|
+
* Called after successful transition or when navigation is no longer valid
|
|
1180
|
+
*/
|
|
1181
|
+
clearPendingNavigation() {
|
|
1182
|
+
this.safeClearItem(STORAGE_KEYS.PENDING_NAVIGATION);
|
|
1183
|
+
}
|
|
1184
|
+
// =============================================================================
|
|
1158
1185
|
// Utility Methods
|
|
1159
1186
|
// =============================================================================
|
|
1160
1187
|
/**
|
|
@@ -1164,6 +1191,7 @@ const _StorageManager = class _StorageManager {
|
|
|
1164
1191
|
this.clearProgress();
|
|
1165
1192
|
this.clearSession();
|
|
1166
1193
|
this.clearAnonymousUserData();
|
|
1194
|
+
this.clearPendingNavigation();
|
|
1167
1195
|
}
|
|
1168
1196
|
};
|
|
1169
1197
|
__publicField(_StorageManager, "instance", null);
|
|
@@ -1836,6 +1864,47 @@ class ShareLinkService {
|
|
|
1836
1864
|
}
|
|
1837
1865
|
}
|
|
1838
1866
|
}
|
|
1867
|
+
const ANALYTICS = {
|
|
1868
|
+
/** Interval for flushing analytics events to the backend (30 seconds) */
|
|
1869
|
+
FLUSH_INTERVAL_MS: 3e4
|
|
1870
|
+
};
|
|
1871
|
+
const TIMING = {
|
|
1872
|
+
// Polling and updates
|
|
1873
|
+
/** Video progress polling interval (50ms) */
|
|
1874
|
+
VIDEO_PROGRESS_POLL_INTERVAL: 50,
|
|
1875
|
+
/** Cursor position update throttle interval (100ms) */
|
|
1876
|
+
CURSOR_UPDATE_THROTTLE: 100,
|
|
1877
|
+
/** Delay for state processing operations (100ms) */
|
|
1878
|
+
STATE_PROCESSING_DELAY_MS: 100,
|
|
1879
|
+
// Analytics
|
|
1880
|
+
/** Analytics event flush interval (30 seconds) */
|
|
1881
|
+
ANALYTICS_FLUSH_INTERVAL: 3e4,
|
|
1882
|
+
// Timeouts
|
|
1883
|
+
/** User data loading timeout (5 seconds) */
|
|
1884
|
+
USER_DATA_TIMEOUT: 5e3,
|
|
1885
|
+
/** Step timeout - player will be destroyed if user stays on same step (120 seconds) */
|
|
1886
|
+
STEP_TIMEOUT: 12e4,
|
|
1887
|
+
/** Retry delay for failed operations (0.5 seconds) */
|
|
1888
|
+
RETRY_DELAY_MS: 500,
|
|
1889
|
+
// DOM and cursor operations
|
|
1890
|
+
/** Delay for DOM stabilization before cursor operations (0.5 seconds) */
|
|
1891
|
+
DOM_STABILIZATION_DELAY_MS: 500,
|
|
1892
|
+
/** Default cursor animation distance in pixels */
|
|
1893
|
+
CURSOR_DEFAULT_DISTANCE: 100,
|
|
1894
|
+
// URL monitoring
|
|
1895
|
+
/** Interval for checking URL path changes (5 seconds) */
|
|
1896
|
+
URL_PATH_CHECK_INTERVAL_MS: 5e3,
|
|
1897
|
+
// Session persistence
|
|
1898
|
+
/** Session expiry time (30 minutes) */
|
|
1899
|
+
SESSION_EXPIRY: 30 * 60 * 1e3,
|
|
1900
|
+
// Cross-page navigation
|
|
1901
|
+
/** Pending navigation expiry time (60 seconds) - longer than normal 6s rule for URL transitions */
|
|
1902
|
+
PENDING_NAVIGATION_EXPIRY: 60 * 1e3
|
|
1903
|
+
};
|
|
1904
|
+
const THRESHOLDS = {
|
|
1905
|
+
/** Minimum scroll distance in pixels to trigger scroll events */
|
|
1906
|
+
SCROLL_THRESHOLD_PX: 10
|
|
1907
|
+
};
|
|
1839
1908
|
class PlayerInitializationService {
|
|
1840
1909
|
constructor(managers) {
|
|
1841
1910
|
__publicField(this, "managers");
|
|
@@ -2000,7 +2069,11 @@ class PlayerInitializationService {
|
|
|
2000
2069
|
if (this.userManagementService) {
|
|
2001
2070
|
this.userManagementService.resolveUserDataLoaded();
|
|
2002
2071
|
}
|
|
2003
|
-
const
|
|
2072
|
+
const resumedFromPendingNav = await this.checkAndResumeFromPendingNavigation();
|
|
2073
|
+
if (resumedFromPendingNav) {
|
|
2074
|
+
log("[PlayerInitializationService.fetchUserData] Resumed from pending URL navigation, skipping other checks");
|
|
2075
|
+
}
|
|
2076
|
+
const resumedPlaylist = resumedFromPendingNav || await this.checkAndResumeInProgressPlaylist(data.watchedPlaylists || {});
|
|
2004
2077
|
if (!resumedPlaylist) {
|
|
2005
2078
|
const shareData = await this.shareLinkService.shouldAutoStartSharePlaylist();
|
|
2006
2079
|
if (shareData && this.playlistOrchestrator) {
|
|
@@ -2086,8 +2159,12 @@ class PlayerInitializationService {
|
|
|
2086
2159
|
watchedPlaylists: anonymousUserData.watchedPlaylists || {}
|
|
2087
2160
|
}
|
|
2088
2161
|
});
|
|
2162
|
+
const resumedFromPendingNav = await this.checkAndResumeFromPendingNavigation();
|
|
2163
|
+
if (resumedFromPendingNav) {
|
|
2164
|
+
log("[PlayerInitializationService.loadAnonymousUserData] Resumed from pending URL navigation, skipping other checks");
|
|
2165
|
+
}
|
|
2089
2166
|
const watchedPlaylists = anonymousUserData.watchedPlaylists || {};
|
|
2090
|
-
const resumedPlaylist = await this.checkAndResumeInProgressPlaylist(watchedPlaylists);
|
|
2167
|
+
const resumedPlaylist = resumedFromPendingNav || await this.checkAndResumeInProgressPlaylist(watchedPlaylists);
|
|
2091
2168
|
if (!resumedPlaylist) {
|
|
2092
2169
|
const shareData = await this.shareLinkService.shouldAutoStartSharePlaylist();
|
|
2093
2170
|
if (shareData && this.playlistOrchestrator) {
|
|
@@ -2159,6 +2236,60 @@ class PlayerInitializationService {
|
|
|
2159
2236
|
}
|
|
2160
2237
|
return false;
|
|
2161
2238
|
}
|
|
2239
|
+
/**
|
|
2240
|
+
* Check for pending navigation from cross-page URL transitions and auto-start the playlist
|
|
2241
|
+
* This handles the case where user navigated to a new page (hard refresh)
|
|
2242
|
+
* and we need to resume from the step that was waiting for that URL
|
|
2243
|
+
* @returns true if a playlist was started from pending navigation
|
|
2244
|
+
*/
|
|
2245
|
+
async checkAndResumeFromPendingNavigation() {
|
|
2246
|
+
const pending = this.managers.storageManager.getPendingNavigation();
|
|
2247
|
+
if (!pending) {
|
|
2248
|
+
return false;
|
|
2249
|
+
}
|
|
2250
|
+
const ageMs = Date.now() - pending.timestamp;
|
|
2251
|
+
if (ageMs > TIMING.PENDING_NAVIGATION_EXPIRY) {
|
|
2252
|
+
this.managers.storageManager.clearPendingNavigation();
|
|
2253
|
+
return false;
|
|
2254
|
+
}
|
|
2255
|
+
if (!this.isURLPathMatch(pending.urlPattern)) {
|
|
2256
|
+
log(`[PlayerInitializationService.checkAndResumeFromPendingNavigation] URL doesn't match pending pattern '${pending.urlPattern}'`);
|
|
2257
|
+
this.managers.storageManager.clearPendingNavigation();
|
|
2258
|
+
return false;
|
|
2259
|
+
}
|
|
2260
|
+
log(`[PlayerInitializationService.checkAndResumeFromPendingNavigation] URL matches! Starting playlist ${pending.playlistId} at step ${pending.nextStepId}`);
|
|
2261
|
+
this.managers.storageManager.clearPendingNavigation();
|
|
2262
|
+
try {
|
|
2263
|
+
if (this.playlistOrchestrator) {
|
|
2264
|
+
await this.playlistOrchestrator.startPlaylist(pending.playlistId, {
|
|
2265
|
+
startNodeId: pending.nextStepId
|
|
2266
|
+
});
|
|
2267
|
+
log(`[PlayerInitializationService.checkAndResumeFromPendingNavigation] Successfully started playlist from pending navigation`);
|
|
2268
|
+
return true;
|
|
2269
|
+
}
|
|
2270
|
+
} catch (error2) {
|
|
2271
|
+
return false;
|
|
2272
|
+
}
|
|
2273
|
+
return false;
|
|
2274
|
+
}
|
|
2275
|
+
/**
|
|
2276
|
+
* Checks if the current URL path matches a pattern
|
|
2277
|
+
* Uses the same logic as TransitionManager for consistency
|
|
2278
|
+
* @param pattern - The URL pattern to match (supports wildcards)
|
|
2279
|
+
* @returns true if the current URL matches the pattern
|
|
2280
|
+
*/
|
|
2281
|
+
isURLPathMatch(pattern) {
|
|
2282
|
+
if (!pattern || typeof window === "undefined") {
|
|
2283
|
+
return false;
|
|
2284
|
+
}
|
|
2285
|
+
const currentUrl = window.location.href;
|
|
2286
|
+
const currentPath = window.location.pathname;
|
|
2287
|
+
const escapedPattern = pattern.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
2288
|
+
const regexPattern = escapedPattern.replace(/\\\*/g, ".*");
|
|
2289
|
+
const regex = new RegExp(regexPattern);
|
|
2290
|
+
const match = regex.test(currentUrl) || regex.test(currentPath);
|
|
2291
|
+
return match;
|
|
2292
|
+
}
|
|
2162
2293
|
/**
|
|
2163
2294
|
* Get or create persistent anonymous user ID
|
|
2164
2295
|
*/
|
|
@@ -6610,44 +6741,6 @@ class VideoManager {
|
|
|
6610
6741
|
this.soundbarElement = null;
|
|
6611
6742
|
}
|
|
6612
6743
|
}
|
|
6613
|
-
const ANALYTICS = {
|
|
6614
|
-
/** Interval for flushing analytics events to the backend (30 seconds) */
|
|
6615
|
-
FLUSH_INTERVAL_MS: 3e4
|
|
6616
|
-
};
|
|
6617
|
-
const TIMING = {
|
|
6618
|
-
// Polling and updates
|
|
6619
|
-
/** Video progress polling interval (50ms) */
|
|
6620
|
-
VIDEO_PROGRESS_POLL_INTERVAL: 50,
|
|
6621
|
-
/** Cursor position update throttle interval (100ms) */
|
|
6622
|
-
CURSOR_UPDATE_THROTTLE: 100,
|
|
6623
|
-
/** Delay for state processing operations (100ms) */
|
|
6624
|
-
STATE_PROCESSING_DELAY_MS: 100,
|
|
6625
|
-
// Analytics
|
|
6626
|
-
/** Analytics event flush interval (30 seconds) */
|
|
6627
|
-
ANALYTICS_FLUSH_INTERVAL: 3e4,
|
|
6628
|
-
// Timeouts
|
|
6629
|
-
/** User data loading timeout (5 seconds) */
|
|
6630
|
-
USER_DATA_TIMEOUT: 5e3,
|
|
6631
|
-
/** Step timeout - player will be destroyed if user stays on same step (120 seconds) */
|
|
6632
|
-
STEP_TIMEOUT: 12e4,
|
|
6633
|
-
/** Retry delay for failed operations (0.5 seconds) */
|
|
6634
|
-
RETRY_DELAY_MS: 500,
|
|
6635
|
-
// DOM and cursor operations
|
|
6636
|
-
/** Delay for DOM stabilization before cursor operations (0.5 seconds) */
|
|
6637
|
-
DOM_STABILIZATION_DELAY_MS: 500,
|
|
6638
|
-
/** Default cursor animation distance in pixels */
|
|
6639
|
-
CURSOR_DEFAULT_DISTANCE: 100,
|
|
6640
|
-
// URL monitoring
|
|
6641
|
-
/** Interval for checking URL path changes (5 seconds) */
|
|
6642
|
-
URL_PATH_CHECK_INTERVAL_MS: 5e3,
|
|
6643
|
-
// Session persistence
|
|
6644
|
-
/** Session expiry time (30 minutes) */
|
|
6645
|
-
SESSION_EXPIRY: 30 * 60 * 1e3
|
|
6646
|
-
};
|
|
6647
|
-
const THRESHOLDS = {
|
|
6648
|
-
/** Minimum scroll distance in pixels to trigger scroll events */
|
|
6649
|
-
SCROLL_THRESHOLD_PX: 10
|
|
6650
|
-
};
|
|
6651
6744
|
const DEFAULT_CONFIG = {
|
|
6652
6745
|
tolerance: 0.3,
|
|
6653
6746
|
// 30% size difference allowed (70% match required)
|
|
@@ -9211,6 +9304,8 @@ class TransitionManager {
|
|
|
9211
9304
|
__publicField(this, "isStateMachineValidating", false);
|
|
9212
9305
|
// Reference to TriggerManager for coordinating playlist triggers
|
|
9213
9306
|
__publicField(this, "triggerManager", null);
|
|
9307
|
+
// beforeunload handler for cross-page URL transitions
|
|
9308
|
+
__publicField(this, "beforeUnloadHandler", null);
|
|
9214
9309
|
/**
|
|
9215
9310
|
* Handles URL changes by checking active URL path transitions and playlist triggers
|
|
9216
9311
|
*/
|
|
@@ -9247,6 +9342,7 @@ class TransitionManager {
|
|
|
9247
9342
|
}
|
|
9248
9343
|
const { pattern, nextStepId } = transition.data;
|
|
9249
9344
|
if (this.isURLPathMatch(pattern)) {
|
|
9345
|
+
StorageManager.getInstance().clearPendingNavigation();
|
|
9250
9346
|
this.triggerTransition(nextStepId);
|
|
9251
9347
|
break;
|
|
9252
9348
|
}
|
|
@@ -9437,6 +9533,8 @@ class TransitionManager {
|
|
|
9437
9533
|
}
|
|
9438
9534
|
const pathPattern = transition.target;
|
|
9439
9535
|
const nextStepId = transition.nextStep;
|
|
9536
|
+
this.savePendingNavigation(pathPattern, nextStepId);
|
|
9537
|
+
this.setupBeforeUnloadHandler(pathPattern, nextStepId);
|
|
9440
9538
|
const initialMatch = this.isURLPathMatch(pathPattern);
|
|
9441
9539
|
if (initialMatch) {
|
|
9442
9540
|
this.triggerTransition(nextStepId);
|
|
@@ -9463,6 +9561,7 @@ class TransitionManager {
|
|
|
9463
9561
|
const match = this.isURLPathMatch(pathPattern);
|
|
9464
9562
|
if (match) {
|
|
9465
9563
|
clearInterval(intervalId);
|
|
9564
|
+
StorageManager.getInstance().clearPendingNavigation();
|
|
9466
9565
|
this.triggerTransition(nextStepId);
|
|
9467
9566
|
}
|
|
9468
9567
|
}, TIMING.URL_PATH_CHECK_INTERVAL_MS);
|
|
@@ -9479,6 +9578,47 @@ class TransitionManager {
|
|
|
9479
9578
|
}
|
|
9480
9579
|
});
|
|
9481
9580
|
}
|
|
9581
|
+
/**
|
|
9582
|
+
* Saves pending navigation data for cross-page URL transitions
|
|
9583
|
+
* This enables resuming from the correct step after a hard page refresh
|
|
9584
|
+
* @param urlPattern - The URL pattern to match
|
|
9585
|
+
* @param nextStepId - The step ID to navigate to
|
|
9586
|
+
*/
|
|
9587
|
+
savePendingNavigation(urlPattern, nextStepId) {
|
|
9588
|
+
const store = getSaltfishStore();
|
|
9589
|
+
if (!store.manifest) {
|
|
9590
|
+
return;
|
|
9591
|
+
}
|
|
9592
|
+
const storageManager2 = StorageManager.getInstance();
|
|
9593
|
+
storageManager2.setPendingNavigation({
|
|
9594
|
+
playlistId: store.manifest.id,
|
|
9595
|
+
nextStepId,
|
|
9596
|
+
urlPattern,
|
|
9597
|
+
timestamp: Date.now()
|
|
9598
|
+
});
|
|
9599
|
+
}
|
|
9600
|
+
/**
|
|
9601
|
+
* Sets up beforeunload handler as backup for cross-page URL transitions
|
|
9602
|
+
* This ensures pending navigation is saved even if the page unloads unexpectedly
|
|
9603
|
+
* @param urlPattern - The URL pattern to match
|
|
9604
|
+
* @param nextStepId - The step ID to navigate to
|
|
9605
|
+
*/
|
|
9606
|
+
setupBeforeUnloadHandler(urlPattern, nextStepId) {
|
|
9607
|
+
this.removeBeforeUnloadHandler();
|
|
9608
|
+
this.beforeUnloadHandler = () => {
|
|
9609
|
+
this.savePendingNavigation(urlPattern, nextStepId);
|
|
9610
|
+
};
|
|
9611
|
+
window.addEventListener("beforeunload", this.beforeUnloadHandler);
|
|
9612
|
+
}
|
|
9613
|
+
/**
|
|
9614
|
+
* Removes the beforeunload handler if it exists
|
|
9615
|
+
*/
|
|
9616
|
+
removeBeforeUnloadHandler() {
|
|
9617
|
+
if (this.beforeUnloadHandler) {
|
|
9618
|
+
window.removeEventListener("beforeunload", this.beforeUnloadHandler);
|
|
9619
|
+
this.beforeUnloadHandler = null;
|
|
9620
|
+
}
|
|
9621
|
+
}
|
|
9482
9622
|
/**
|
|
9483
9623
|
* Checks if the current URL path matches a pattern
|
|
9484
9624
|
*/
|
|
@@ -9588,6 +9728,7 @@ class TransitionManager {
|
|
|
9588
9728
|
});
|
|
9589
9729
|
this.activeTransitions.clear();
|
|
9590
9730
|
this.waitingForInteraction = false;
|
|
9731
|
+
this.removeBeforeUnloadHandler();
|
|
9591
9732
|
}
|
|
9592
9733
|
/**
|
|
9593
9734
|
* Sets the waiting for interaction state
|
|
@@ -10824,6 +10965,11 @@ class PlaylistLoader {
|
|
|
10824
10965
|
const manifestIdForProgress = manifest.id;
|
|
10825
10966
|
const wasTriggered = options._triggeredByTriggerManager === true;
|
|
10826
10967
|
let startStepId = manifest.startStep;
|
|
10968
|
+
const pendingNav = this.checkPendingNavigation(manifest);
|
|
10969
|
+
if (pendingNav) {
|
|
10970
|
+
log(`PlaylistLoader: Resuming from pending URL navigation to step '${pendingNav.nextStepId}'`);
|
|
10971
|
+
return pendingNav.nextStepId;
|
|
10972
|
+
}
|
|
10827
10973
|
if (options.startNodeId) {
|
|
10828
10974
|
const customStep = manifest.steps.find((step) => step.id === options.startNodeId);
|
|
10829
10975
|
if (customStep) {
|
|
@@ -10855,6 +11001,61 @@ class PlaylistLoader {
|
|
|
10855
11001
|
}
|
|
10856
11002
|
return startStepId;
|
|
10857
11003
|
}
|
|
11004
|
+
/**
|
|
11005
|
+
* Checks for pending navigation from a cross-page URL transition
|
|
11006
|
+
* This handles the case where user navigated to a new page (hard refresh)
|
|
11007
|
+
* and we need to resume from the step that was waiting for that URL
|
|
11008
|
+
* @param manifest - The loaded playlist manifest
|
|
11009
|
+
* @returns The pending navigation data if valid, null otherwise
|
|
11010
|
+
*/
|
|
11011
|
+
checkPendingNavigation(manifest) {
|
|
11012
|
+
const storageManager2 = StorageManager.getInstance();
|
|
11013
|
+
const pending = storageManager2.getPendingNavigation();
|
|
11014
|
+
if (!pending) {
|
|
11015
|
+
return null;
|
|
11016
|
+
}
|
|
11017
|
+
if (pending.playlistId !== manifest.id) {
|
|
11018
|
+
log(`PlaylistLoader: Pending navigation is for different playlist (${pending.playlistId}), ignoring`);
|
|
11019
|
+
return null;
|
|
11020
|
+
}
|
|
11021
|
+
const ageMs = Date.now() - pending.timestamp;
|
|
11022
|
+
if (ageMs > TIMING.PENDING_NAVIGATION_EXPIRY) {
|
|
11023
|
+
storageManager2.clearPendingNavigation();
|
|
11024
|
+
return null;
|
|
11025
|
+
}
|
|
11026
|
+
if (!this.isURLPathMatch(pending.urlPattern)) {
|
|
11027
|
+
log(`PlaylistLoader: URL doesn't match pending pattern '${pending.urlPattern}', clearing`);
|
|
11028
|
+
storageManager2.clearPendingNavigation();
|
|
11029
|
+
return null;
|
|
11030
|
+
}
|
|
11031
|
+
const targetStep = manifest.steps.find((step) => step.id === pending.nextStepId);
|
|
11032
|
+
if (!targetStep) {
|
|
11033
|
+
log(`PlaylistLoader: Pending navigation target step '${pending.nextStepId}' not found in manifest, clearing`);
|
|
11034
|
+
storageManager2.clearPendingNavigation();
|
|
11035
|
+
return null;
|
|
11036
|
+
}
|
|
11037
|
+
log(`PlaylistLoader: Using pending navigation to step '${pending.nextStepId}' (${Math.round(ageMs / 1e3)}s old)`);
|
|
11038
|
+
storageManager2.clearPendingNavigation();
|
|
11039
|
+
return pending;
|
|
11040
|
+
}
|
|
11041
|
+
/**
|
|
11042
|
+
* Checks if the current URL path matches a pattern
|
|
11043
|
+
* Uses the same logic as TransitionManager for consistency
|
|
11044
|
+
* @param pattern - The URL pattern to match (supports wildcards)
|
|
11045
|
+
* @returns true if the current URL matches the pattern
|
|
11046
|
+
*/
|
|
11047
|
+
isURLPathMatch(pattern) {
|
|
11048
|
+
if (!pattern) {
|
|
11049
|
+
return false;
|
|
11050
|
+
}
|
|
11051
|
+
const currentUrl = window.location.href;
|
|
11052
|
+
const currentPath = window.location.pathname;
|
|
11053
|
+
const escapedPattern = pattern.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
11054
|
+
const regexPattern = escapedPattern.replace(/\\\*/g, ".*");
|
|
11055
|
+
const regex = new RegExp(regexPattern);
|
|
11056
|
+
const match = regex.test(currentUrl) || regex.test(currentPath);
|
|
11057
|
+
return match;
|
|
11058
|
+
}
|
|
10858
11059
|
}
|
|
10859
11060
|
class PlaylistManager extends EventSubscriberManager {
|
|
10860
11061
|
/**
|
|
@@ -12268,7 +12469,7 @@ const SaltfishPlayer$1 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.de
|
|
|
12268
12469
|
__proto__: null,
|
|
12269
12470
|
SaltfishPlayer
|
|
12270
12471
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
12271
|
-
const version = "0.3.
|
|
12472
|
+
const version = "0.3.63";
|
|
12272
12473
|
const packageJson = {
|
|
12273
12474
|
version
|
|
12274
12475
|
};
|