pstream is dead; long live pstream taciturnaxolotl.github.io/pstream-ng/
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

fix skip time fetching with a slice cache

Pas 6bfb07f8 644b6ca8

+50 -10
+18 -9
src/components/player/hooks/useSkipTime.ts
··· 1 - import { useEffect, useState } from "react"; 1 + import { useEffect } from "react"; 2 2 3 3 // import { proxiedFetch } from "@/backend/helpers/fetch"; 4 4 import { mwFetch, proxiedFetch } from "@/backend/helpers/fetch"; 5 5 import { usePlayerMeta } from "@/components/player/hooks/usePlayerMeta"; 6 6 import { conf } from "@/setup/config"; 7 + import { usePlayerStore } from "@/stores/player/store"; 8 + import { getMediaKey } from "@/stores/player/slices/source"; 7 9 import { usePreferencesStore } from "@/stores/preferences"; 8 10 import { getTurnstileToken } from "@/utils/turnstile"; 9 11 ··· 30 32 31 33 export function useSkipTime() { 32 34 const { playerMeta: meta } = usePlayerMeta(); 33 - const [segments, setSegments] = useState<SegmentData[]>([]); 34 35 const febboxKey = usePreferencesStore((s) => s.febboxKey); 36 + const cacheKey = getMediaKey(meta ?? null); 37 + const skipSegmentsCacheKey = usePlayerStore((s) => s.skipSegmentsCacheKey); 38 + const skipSegments = usePlayerStore((s) => s.skipSegments); 39 + const setSkipSegments = usePlayerStore((s) => s.setSkipSegments); 35 40 36 41 useEffect(() => { 42 + if (!cacheKey) return; 43 + // Already have segments for this media – don't refetch (e.g. when opening menu) 44 + if (cacheKey === skipSegmentsCacheKey) return; 37 45 // Validate segment data according to rules 38 46 // eslint-disable-next-line camelcase 39 47 const validateSegment = ( ··· 212 220 }; 213 221 214 222 const fetchSkipTime = async (): Promise<void> => { 215 - // Reset source and segments 216 223 currentSkipTimeSource = null; 217 - setSegments([]); 218 224 219 225 // Try TheIntroDB API first (supports both movies and TV shows with full segment data) 220 226 const theIntroDBSegments = await fetchTheIntroDBSegments(); ··· 228 234 // If we have a valid intro from TIDB, use all TIDB segments 229 235 if (hasIntroSegment) { 230 236 currentSkipTimeSource = "theintrodb"; 231 - setSegments(theIntroDBSegments); 237 + setSkipSegments(cacheKey, theIntroDBSegments); 232 238 return; 233 239 } 234 240 ··· 275 281 // Add any valid recap/credits segments from TIDB 276 282 finalSegments.push(...nonIntroSegments); 277 283 278 - if (finalSegments.length > 0) { 279 - setSegments(finalSegments); 280 - } 284 + // Always update cache (even when empty) so we don't refetch for this media 285 + setSkipSegments(cacheKey, finalSegments); 281 286 }; 282 287 283 288 fetchSkipTime(); 284 289 }, [ 290 + cacheKey, 291 + skipSegmentsCacheKey, 292 + setSkipSegments, 285 293 meta?.tmdbId, 286 294 meta?.imdbId, 287 295 meta?.title, ··· 291 299 febboxKey, 292 300 ]); 293 301 294 - return segments; 302 + // Only return segments when they're for the current media (avoid showing stale data) 303 + return cacheKey === skipSegmentsCacheKey ? skipSegments : []; 295 304 }
+26
src/stores/player/slices/skipSegments.ts
··· 1 + import type { SegmentData } from "@/components/player/hooks/useSkipTime"; 2 + import { MakeSlice } from "@/stores/player/slices/types"; 3 + 4 + export interface SkipSegmentsSlice { 5 + skipSegmentsCacheKey: string | null; 6 + skipSegments: SegmentData[]; 7 + setSkipSegments(cacheKey: string, segments: SegmentData[]): void; 8 + clearSkipSegments(): void; 9 + } 10 + 11 + export const createSkipSegmentsSlice: MakeSlice<SkipSegmentsSlice> = (set) => ({ 12 + skipSegmentsCacheKey: null, 13 + skipSegments: [], 14 + setSkipSegments(cacheKey, segments) { 15 + set((s) => { 16 + s.skipSegmentsCacheKey = cacheKey; 17 + s.skipSegments = segments; 18 + }); 19 + }, 20 + clearSkipSegments() { 21 + set((s) => { 22 + s.skipSegmentsCacheKey = null; 23 + s.skipSegments = []; 24 + }); 25 + }, 26 + });
+1
src/stores/player/slices/source.ts
··· 396 396 }); 397 397 }, 398 398 reset() { 399 + get().clearSkipSegments?.(); 399 400 set((s) => { 400 401 s.source = null; 401 402 s.sourceId = null;
+3 -1
src/stores/player/slices/types.ts
··· 5 5 import { InterfaceSlice } from "@/stores/player/slices/interface"; 6 6 import { PlayingSlice } from "@/stores/player/slices/playing"; 7 7 import { ProgressSlice } from "@/stores/player/slices/progress"; 8 + import { SkipSegmentsSlice } from "@/stores/player/slices/skipSegments"; 8 9 import { SourceSlice } from "@/stores/player/slices/source"; 9 10 import { ThumbnailSlice } from "@/stores/player/slices/thumbnails"; 10 11 ··· 14 15 SourceSlice & 15 16 DisplaySlice & 16 17 CastingSlice & 17 - ThumbnailSlice; 18 + ThumbnailSlice & 19 + SkipSegmentsSlice; 18 20 export type MakeSlice<Slice> = StateCreator< 19 21 AllSlices, 20 22 [["zustand/immer", never]],
+2
src/stores/player/store.ts
··· 6 6 import { createInterfaceSlice } from "@/stores/player/slices/interface"; 7 7 import { createPlayingSlice } from "@/stores/player/slices/playing"; 8 8 import { createProgressSlice } from "@/stores/player/slices/progress"; 9 + import { createSkipSegmentsSlice } from "@/stores/player/slices/skipSegments"; 9 10 import { createSourceSlice } from "@/stores/player/slices/source"; 10 11 import { createThumbnailSlice } from "@/stores/player/slices/thumbnails"; 11 12 import { AllSlices } from "@/stores/player/slices/types"; ··· 19 20 ...createDisplaySlice(...a), 20 21 ...createCastingSlice(...a), 21 22 ...createThumbnailSlice(...a), 23 + ...createSkipSegmentsSlice(...a), 22 24 })), 23 25 );