Revert "refactor media failure tracking"

This reverts commit f68bb15c57.
This commit is contained in:
Pas 2025-12-17 12:27:37 -07:00
parent f68bb15c57
commit 36069f8193
7 changed files with 16 additions and 186 deletions

View file

@ -175,28 +175,12 @@ export function useScrape() {
const failedSources = playerState.failedSources;
const failedEmbeds = playerState.failedEmbeds;
// Get media-specific failures
const mediaFailureKey = {
type: media.type,
tmdbId: media.tmdbId,
...(media.type === "show" && media.episode && media.season
? {
seasonNumber: media.season.number,
episodeNumber: media.episode.number,
}
: {}),
};
const mediaFailures = playerState.getMediaFailures(mediaFailureKey);
const mediaFailedSources = mediaFailures.failedSources;
const mediaFailedEmbeds = mediaFailures.failedEmbeds;
// Start with all available sources (filtered by disabled and failed ones)
let baseSourceOrder = allSources
.filter(
(source) =>
!(disabledSources || []).includes(source.id) &&
!failedSources.includes(source.id) &&
!mediaFailedSources.includes(source.id),
!failedSources.includes(source.id),
)
.map((source) => source.id);
@ -238,17 +222,15 @@ export function useScrape() {
}
}
// Collect all failed embed IDs across all sources (both global and media-specific)
// Collect all failed embed IDs across all sources
const allFailedEmbedIds = Object.values(failedEmbeds).flat();
const allMediaFailedEmbedIds = Object.values(mediaFailedEmbeds).flat();
// Filter out disabled and failed embeds from the embed order
const filteredEmbedOrder = enableEmbedOrder
? (preferredEmbedOrder || []).filter(
(id) =>
!(disabledEmbeds || []).includes(id) &&
!allFailedEmbedIds.includes(id) &&
!allMediaFailedEmbedIds.includes(id),
!allFailedEmbedIds.includes(id),
)
: undefined;

View file

@ -24,10 +24,9 @@ export function PlaybackErrorPart(props: PlaybackErrorPartProps) {
const playbackError = usePlayerStore((s) => s.interface.error);
const currentSourceId = usePlayerStore((s) => s.sourceId);
const currentEmbedId = usePlayerStore((s) => s.embedId);
const meta = usePlayerStore((s) => s.meta);
const addMediaFailedSource = usePlayerStore((s) => s.addMediaFailedSource);
const addMediaFailedEmbed = usePlayerStore((s) => s.addMediaFailedEmbed);
const getMediaFailures = usePlayerStore((s) => s.getMediaFailures);
const addFailedSource = usePlayerStore((s) => s.addFailedSource);
const addFailedEmbed = usePlayerStore((s) => s.addFailedEmbed);
const failedEmbeds = usePlayerStore((s) => s.failedEmbeds);
const modal = useModal("error");
const settingsRouter = useOverlayRouter("settings");
const hasOpenedSettings = useRef(false);
@ -41,7 +40,7 @@ export function PlaybackErrorPart(props: PlaybackErrorPartProps) {
// Mark the failed source/embed and handle UI when a playback error occurs
useEffect(() => {
if (playbackError && currentSourceId && meta) {
if (playbackError && currentSourceId) {
// Only mark source/embed as failed for fatal errors
const isFatalError =
playbackError.type === "hls"
@ -49,37 +48,21 @@ export function PlaybackErrorPart(props: PlaybackErrorPartProps) {
: playbackError.type === "htmlvideo";
if (isFatalError) {
// Create media failure key
const mediaFailureKey = {
type: meta.type,
tmdbId: meta.tmdbId,
...(meta.type === "show" && meta.episode && meta.season
? {
seasonNumber: meta.season.number,
episodeNumber: meta.episode.number,
}
: {}),
};
// Get current media failures
const mediaFailures = getMediaFailures(mediaFailureKey);
// If there's an active embed, disable that embed instead of the source
if (currentEmbedId) {
addMediaFailedEmbed(mediaFailureKey, currentSourceId, currentEmbedId);
addFailedEmbed(currentSourceId, currentEmbedId);
// Check if all embeds for this source have now failed
// If so, disable the entire source
const failedEmbedsForSource =
mediaFailures.failedEmbeds[currentSourceId] || [];
const failedEmbedsForSource = failedEmbeds[currentSourceId] || [];
// For now, we'll assume if we have 2+ failed embeds for a source, disable it
// This is a simple heuristic - we could make it more sophisticated
if (failedEmbedsForSource.length >= 2) {
addMediaFailedSource(mediaFailureKey, currentSourceId);
addFailedSource(currentSourceId);
}
} else {
// No embed active, disable the source
addMediaFailedSource(mediaFailureKey, currentSourceId);
addFailedSource(currentSourceId);
}
}
@ -95,10 +78,9 @@ export function PlaybackErrorPart(props: PlaybackErrorPartProps) {
playbackError,
currentSourceId,
currentEmbedId,
meta,
getMediaFailures,
addMediaFailedSource,
addMediaFailedEmbed,
failedEmbeds,
addFailedSource,
addFailedEmbed,
settingsRouter,
setLastSuccessfulSource,
enableAutoResumeOnPlaybackError,

View file

@ -41,10 +41,7 @@ import { RegisterPage } from "@/pages/Register";
import { SupportPage } from "@/pages/Support";
import { Layout } from "@/setup/Layout";
import { useHistoryListener } from "@/stores/history";
import {
useClearMediaFailuresOnNavigation,
useClearModalsOnNavigation,
} from "@/stores/interface/overlayStack";
import { useClearModalsOnNavigation } from "@/stores/interface/overlayStack";
import { LanguageProvider } from "@/stores/language";
const DeveloperPage = lazy(() => import("@/pages/DeveloperPage"));
@ -110,7 +107,6 @@ function App() {
useOnlineListener();
useGlobalKeyboardEvents();
useClearModalsOnNavigation();
useClearMediaFailuresOnNavigation();
const maintenance = false; // Shows maintance page
const [showDowntime, setShowDowntime] = useState(maintenance);

View file

@ -3,8 +3,6 @@ import { useLocation } from "react-router-dom";
import { create } from "zustand";
import { immer } from "zustand/middleware/immer";
import { usePlayerStore } from "@/stores/player/store";
type OverlayType = "volume" | "subtitle" | "speed" | null;
interface ModalData {
@ -77,15 +75,3 @@ export function useClearModalsOnNavigation() {
clearAllModals();
}, [location.pathname, clearAllModals]);
}
// Hook to clear media failures on navigation
export function useClearMediaFailuresOnNavigation() {
const location = useLocation();
const clearAllMediaFailures = usePlayerStore(
(state) => state.clearAllMediaFailures,
);
useEffect(() => {
clearAllMediaFailures();
}, [location.pathname, clearAllMediaFailures]);
}

View file

@ -1,112 +0,0 @@
import { MakeSlice } from "@/stores/player/slices/types";
export interface MediaFailureKey {
type: "movie" | "show";
tmdbId: string;
seasonNumber?: number;
episodeNumber?: number;
}
export interface MediaFailuresSlice {
mediaFailures: Record<
string,
{
failedSources: string[];
failedEmbeds: Record<string, string[]>;
}
>;
getMediaFailureKey(meta: MediaFailureKey): string;
getMediaFailures(meta: MediaFailureKey): {
failedSources: string[];
failedEmbeds: Record<string, string[]>;
};
addMediaFailedSource(meta: MediaFailureKey, sourceId: string): void;
addMediaFailedEmbed(
meta: MediaFailureKey,
sourceId: string,
embedId: string,
): void;
clearMediaFailures(meta: MediaFailureKey): void;
clearAllMediaFailures(): void;
reset(): void;
}
function createMediaFailureKey(meta: MediaFailureKey): string {
const baseKey = `${meta.type}-${meta.tmdbId}`;
if (
meta.type === "show" &&
meta.seasonNumber !== undefined &&
meta.episodeNumber !== undefined
) {
return `${baseKey}-s${meta.seasonNumber}e${meta.episodeNumber}`;
}
return baseKey;
}
export const createMediaFailuresSlice: MakeSlice<MediaFailuresSlice> = (
set,
get,
) => ({
mediaFailures: {},
getMediaFailureKey(meta) {
return createMediaFailureKey(meta);
},
getMediaFailures(meta) {
const key = createMediaFailureKey(meta);
return get().mediaFailures[key] || { failedSources: [], failedEmbeds: {} };
},
addMediaFailedSource(meta, sourceId) {
const key = createMediaFailureKey(meta);
set((s) => {
if (!s.mediaFailures[key]) {
s.mediaFailures[key] = { failedSources: [], failedEmbeds: {} };
}
if (!s.mediaFailures[key].failedSources.includes(sourceId)) {
s.mediaFailures[key].failedSources = [
...s.mediaFailures[key].failedSources,
sourceId,
];
}
});
},
addMediaFailedEmbed(meta, sourceId, embedId) {
const key = createMediaFailureKey(meta);
set((s) => {
if (!s.mediaFailures[key]) {
s.mediaFailures[key] = { failedSources: [], failedEmbeds: {} };
}
if (!s.mediaFailures[key].failedEmbeds[sourceId]) {
s.mediaFailures[key].failedEmbeds[sourceId] = [];
}
if (!s.mediaFailures[key].failedEmbeds[sourceId].includes(embedId)) {
s.mediaFailures[key].failedEmbeds[sourceId] = [
...s.mediaFailures[key].failedEmbeds[sourceId],
embedId,
];
}
});
},
clearMediaFailures(meta) {
const key = createMediaFailureKey(meta);
set((s) => {
delete s.mediaFailures[key];
});
},
clearAllMediaFailures() {
set((s) => {
s.mediaFailures = {};
});
},
reset() {
set((s) => {
s.mediaFailures = {};
});
},
});

View file

@ -3,7 +3,6 @@ import { StateCreator } from "zustand";
import { CastingSlice } from "@/stores/player/slices/casting";
import { DisplaySlice } from "@/stores/player/slices/display";
import { InterfaceSlice } from "@/stores/player/slices/interface";
import { MediaFailuresSlice } from "@/stores/player/slices/mediaFailures";
import { PlayingSlice } from "@/stores/player/slices/playing";
import { ProgressSlice } from "@/stores/player/slices/progress";
import { SourceSlice } from "@/stores/player/slices/source";
@ -15,8 +14,7 @@ export type AllSlices = InterfaceSlice &
SourceSlice &
DisplaySlice &
CastingSlice &
ThumbnailSlice &
MediaFailuresSlice;
ThumbnailSlice;
export type MakeSlice<Slice> = StateCreator<
AllSlices,
[["zustand/immer", never]],

View file

@ -4,7 +4,6 @@ import { immer } from "zustand/middleware/immer";
import { createCastingSlice } from "@/stores/player/slices/casting";
import { createDisplaySlice } from "@/stores/player/slices/display";
import { createInterfaceSlice } from "@/stores/player/slices/interface";
import { createMediaFailuresSlice } from "@/stores/player/slices/mediaFailures";
import { createPlayingSlice } from "@/stores/player/slices/playing";
import { createProgressSlice } from "@/stores/player/slices/progress";
import { createSourceSlice } from "@/stores/player/slices/source";
@ -20,6 +19,5 @@ export const usePlayerStore = create(
...createDisplaySlice(...a),
...createCastingSlice(...a),
...createThumbnailSlice(...a),
...createMediaFailuresSlice(...a),
})),
);