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.

Revert "refactor media failure tracking"

This reverts commit f68bb15c57da65848cbde100d0312f7c37fe153c.

Pas 36069f81 f68bb15c

+16 -186
+3 -21
src/hooks/useProviderScrape.tsx
··· 175 175 const failedSources = playerState.failedSources; 176 176 const failedEmbeds = playerState.failedEmbeds; 177 177 178 - // Get media-specific failures 179 - const mediaFailureKey = { 180 - type: media.type, 181 - tmdbId: media.tmdbId, 182 - ...(media.type === "show" && media.episode && media.season 183 - ? { 184 - seasonNumber: media.season.number, 185 - episodeNumber: media.episode.number, 186 - } 187 - : {}), 188 - }; 189 - const mediaFailures = playerState.getMediaFailures(mediaFailureKey); 190 - const mediaFailedSources = mediaFailures.failedSources; 191 - const mediaFailedEmbeds = mediaFailures.failedEmbeds; 192 - 193 178 // Start with all available sources (filtered by disabled and failed ones) 194 179 let baseSourceOrder = allSources 195 180 .filter( 196 181 (source) => 197 182 !(disabledSources || []).includes(source.id) && 198 - !failedSources.includes(source.id) && 199 - !mediaFailedSources.includes(source.id), 183 + !failedSources.includes(source.id), 200 184 ) 201 185 .map((source) => source.id); 202 186 ··· 238 222 } 239 223 } 240 224 241 - // Collect all failed embed IDs across all sources (both global and media-specific) 225 + // Collect all failed embed IDs across all sources 242 226 const allFailedEmbedIds = Object.values(failedEmbeds).flat(); 243 - const allMediaFailedEmbedIds = Object.values(mediaFailedEmbeds).flat(); 244 227 245 228 // Filter out disabled and failed embeds from the embed order 246 229 const filteredEmbedOrder = enableEmbedOrder 247 230 ? (preferredEmbedOrder || []).filter( 248 231 (id) => 249 232 !(disabledEmbeds || []).includes(id) && 250 - !allFailedEmbedIds.includes(id) && 251 - !allMediaFailedEmbedIds.includes(id), 233 + !allFailedEmbedIds.includes(id), 252 234 ) 253 235 : undefined; 254 236
+11 -29
src/pages/parts/player/PlaybackErrorPart.tsx
··· 24 24 const playbackError = usePlayerStore((s) => s.interface.error); 25 25 const currentSourceId = usePlayerStore((s) => s.sourceId); 26 26 const currentEmbedId = usePlayerStore((s) => s.embedId); 27 - const meta = usePlayerStore((s) => s.meta); 28 - const addMediaFailedSource = usePlayerStore((s) => s.addMediaFailedSource); 29 - const addMediaFailedEmbed = usePlayerStore((s) => s.addMediaFailedEmbed); 30 - const getMediaFailures = usePlayerStore((s) => s.getMediaFailures); 27 + const addFailedSource = usePlayerStore((s) => s.addFailedSource); 28 + const addFailedEmbed = usePlayerStore((s) => s.addFailedEmbed); 29 + const failedEmbeds = usePlayerStore((s) => s.failedEmbeds); 31 30 const modal = useModal("error"); 32 31 const settingsRouter = useOverlayRouter("settings"); 33 32 const hasOpenedSettings = useRef(false); ··· 41 40 42 41 // Mark the failed source/embed and handle UI when a playback error occurs 43 42 useEffect(() => { 44 - if (playbackError && currentSourceId && meta) { 43 + if (playbackError && currentSourceId) { 45 44 // Only mark source/embed as failed for fatal errors 46 45 const isFatalError = 47 46 playbackError.type === "hls" ··· 49 48 : playbackError.type === "htmlvideo"; 50 49 51 50 if (isFatalError) { 52 - // Create media failure key 53 - const mediaFailureKey = { 54 - type: meta.type, 55 - tmdbId: meta.tmdbId, 56 - ...(meta.type === "show" && meta.episode && meta.season 57 - ? { 58 - seasonNumber: meta.season.number, 59 - episodeNumber: meta.episode.number, 60 - } 61 - : {}), 62 - }; 63 - 64 - // Get current media failures 65 - const mediaFailures = getMediaFailures(mediaFailureKey); 66 - 67 51 // If there's an active embed, disable that embed instead of the source 68 52 if (currentEmbedId) { 69 - addMediaFailedEmbed(mediaFailureKey, currentSourceId, currentEmbedId); 53 + addFailedEmbed(currentSourceId, currentEmbedId); 70 54 71 55 // Check if all embeds for this source have now failed 72 56 // If so, disable the entire source 73 - const failedEmbedsForSource = 74 - mediaFailures.failedEmbeds[currentSourceId] || []; 57 + const failedEmbedsForSource = failedEmbeds[currentSourceId] || []; 75 58 // For now, we'll assume if we have 2+ failed embeds for a source, disable it 76 59 // This is a simple heuristic - we could make it more sophisticated 77 60 if (failedEmbedsForSource.length >= 2) { 78 - addMediaFailedSource(mediaFailureKey, currentSourceId); 61 + addFailedSource(currentSourceId); 79 62 } 80 63 } else { 81 64 // No embed active, disable the source 82 - addMediaFailedSource(mediaFailureKey, currentSourceId); 65 + addFailedSource(currentSourceId); 83 66 } 84 67 } 85 68 ··· 95 78 playbackError, 96 79 currentSourceId, 97 80 currentEmbedId, 98 - meta, 99 - getMediaFailures, 100 - addMediaFailedSource, 101 - addMediaFailedEmbed, 81 + failedEmbeds, 82 + addFailedSource, 83 + addFailedEmbed, 102 84 settingsRouter, 103 85 setLastSuccessfulSource, 104 86 enableAutoResumeOnPlaybackError,
+1 -5
src/setup/App.tsx
··· 41 41 import { SupportPage } from "@/pages/Support"; 42 42 import { Layout } from "@/setup/Layout"; 43 43 import { useHistoryListener } from "@/stores/history"; 44 - import { 45 - useClearMediaFailuresOnNavigation, 46 - useClearModalsOnNavigation, 47 - } from "@/stores/interface/overlayStack"; 44 + import { useClearModalsOnNavigation } from "@/stores/interface/overlayStack"; 48 45 import { LanguageProvider } from "@/stores/language"; 49 46 50 47 const DeveloperPage = lazy(() => import("@/pages/DeveloperPage")); ··· 110 107 useOnlineListener(); 111 108 useGlobalKeyboardEvents(); 112 109 useClearModalsOnNavigation(); 113 - useClearMediaFailuresOnNavigation(); 114 110 const maintenance = false; // Shows maintance page 115 111 const [showDowntime, setShowDowntime] = useState(maintenance); 116 112
-14
src/stores/interface/overlayStack.ts
··· 3 3 import { create } from "zustand"; 4 4 import { immer } from "zustand/middleware/immer"; 5 5 6 - import { usePlayerStore } from "@/stores/player/store"; 7 - 8 6 type OverlayType = "volume" | "subtitle" | "speed" | null; 9 7 10 8 interface ModalData { ··· 77 75 clearAllModals(); 78 76 }, [location.pathname, clearAllModals]); 79 77 } 80 - 81 - // Hook to clear media failures on navigation 82 - export function useClearMediaFailuresOnNavigation() { 83 - const location = useLocation(); 84 - const clearAllMediaFailures = usePlayerStore( 85 - (state) => state.clearAllMediaFailures, 86 - ); 87 - 88 - useEffect(() => { 89 - clearAllMediaFailures(); 90 - }, [location.pathname, clearAllMediaFailures]); 91 - }
-112
src/stores/player/slices/mediaFailures.ts
··· 1 - import { MakeSlice } from "@/stores/player/slices/types"; 2 - 3 - export interface MediaFailureKey { 4 - type: "movie" | "show"; 5 - tmdbId: string; 6 - seasonNumber?: number; 7 - episodeNumber?: number; 8 - } 9 - 10 - export interface MediaFailuresSlice { 11 - mediaFailures: Record< 12 - string, 13 - { 14 - failedSources: string[]; 15 - failedEmbeds: Record<string, string[]>; 16 - } 17 - >; 18 - getMediaFailureKey(meta: MediaFailureKey): string; 19 - getMediaFailures(meta: MediaFailureKey): { 20 - failedSources: string[]; 21 - failedEmbeds: Record<string, string[]>; 22 - }; 23 - addMediaFailedSource(meta: MediaFailureKey, sourceId: string): void; 24 - addMediaFailedEmbed( 25 - meta: MediaFailureKey, 26 - sourceId: string, 27 - embedId: string, 28 - ): void; 29 - clearMediaFailures(meta: MediaFailureKey): void; 30 - clearAllMediaFailures(): void; 31 - reset(): void; 32 - } 33 - 34 - function createMediaFailureKey(meta: MediaFailureKey): string { 35 - const baseKey = `${meta.type}-${meta.tmdbId}`; 36 - if ( 37 - meta.type === "show" && 38 - meta.seasonNumber !== undefined && 39 - meta.episodeNumber !== undefined 40 - ) { 41 - return `${baseKey}-s${meta.seasonNumber}e${meta.episodeNumber}`; 42 - } 43 - return baseKey; 44 - } 45 - 46 - export const createMediaFailuresSlice: MakeSlice<MediaFailuresSlice> = ( 47 - set, 48 - get, 49 - ) => ({ 50 - mediaFailures: {}, 51 - 52 - getMediaFailureKey(meta) { 53 - return createMediaFailureKey(meta); 54 - }, 55 - 56 - getMediaFailures(meta) { 57 - const key = createMediaFailureKey(meta); 58 - return get().mediaFailures[key] || { failedSources: [], failedEmbeds: {} }; 59 - }, 60 - 61 - addMediaFailedSource(meta, sourceId) { 62 - const key = createMediaFailureKey(meta); 63 - set((s) => { 64 - if (!s.mediaFailures[key]) { 65 - s.mediaFailures[key] = { failedSources: [], failedEmbeds: {} }; 66 - } 67 - if (!s.mediaFailures[key].failedSources.includes(sourceId)) { 68 - s.mediaFailures[key].failedSources = [ 69 - ...s.mediaFailures[key].failedSources, 70 - sourceId, 71 - ]; 72 - } 73 - }); 74 - }, 75 - 76 - addMediaFailedEmbed(meta, sourceId, embedId) { 77 - const key = createMediaFailureKey(meta); 78 - set((s) => { 79 - if (!s.mediaFailures[key]) { 80 - s.mediaFailures[key] = { failedSources: [], failedEmbeds: {} }; 81 - } 82 - if (!s.mediaFailures[key].failedEmbeds[sourceId]) { 83 - s.mediaFailures[key].failedEmbeds[sourceId] = []; 84 - } 85 - if (!s.mediaFailures[key].failedEmbeds[sourceId].includes(embedId)) { 86 - s.mediaFailures[key].failedEmbeds[sourceId] = [ 87 - ...s.mediaFailures[key].failedEmbeds[sourceId], 88 - embedId, 89 - ]; 90 - } 91 - }); 92 - }, 93 - 94 - clearMediaFailures(meta) { 95 - const key = createMediaFailureKey(meta); 96 - set((s) => { 97 - delete s.mediaFailures[key]; 98 - }); 99 - }, 100 - 101 - clearAllMediaFailures() { 102 - set((s) => { 103 - s.mediaFailures = {}; 104 - }); 105 - }, 106 - 107 - reset() { 108 - set((s) => { 109 - s.mediaFailures = {}; 110 - }); 111 - }, 112 - });
+1 -3
src/stores/player/slices/types.ts
··· 3 3 import { CastingSlice } from "@/stores/player/slices/casting"; 4 4 import { DisplaySlice } from "@/stores/player/slices/display"; 5 5 import { InterfaceSlice } from "@/stores/player/slices/interface"; 6 - import { MediaFailuresSlice } from "@/stores/player/slices/mediaFailures"; 7 6 import { PlayingSlice } from "@/stores/player/slices/playing"; 8 7 import { ProgressSlice } from "@/stores/player/slices/progress"; 9 8 import { SourceSlice } from "@/stores/player/slices/source"; ··· 15 14 SourceSlice & 16 15 DisplaySlice & 17 16 CastingSlice & 18 - ThumbnailSlice & 19 - MediaFailuresSlice; 17 + ThumbnailSlice; 20 18 export type MakeSlice<Slice> = StateCreator< 21 19 AllSlices, 22 20 [["zustand/immer", never]],
-2
src/stores/player/store.ts
··· 4 4 import { createCastingSlice } from "@/stores/player/slices/casting"; 5 5 import { createDisplaySlice } from "@/stores/player/slices/display"; 6 6 import { createInterfaceSlice } from "@/stores/player/slices/interface"; 7 - import { createMediaFailuresSlice } from "@/stores/player/slices/mediaFailures"; 8 7 import { createPlayingSlice } from "@/stores/player/slices/playing"; 9 8 import { createProgressSlice } from "@/stores/player/slices/progress"; 10 9 import { createSourceSlice } from "@/stores/player/slices/source"; ··· 20 19 ...createDisplaySlice(...a), 21 20 ...createCastingSlice(...a), 22 21 ...createThumbnailSlice(...a), 23 - ...createMediaFailuresSlice(...a), 24 22 })), 25 23 );