refactor(casting): extract useCastPlayerItem hook

This commit is contained in:
Uruk
2026-05-22 01:15:29 +02:00
parent 9f4f0fa7d1
commit 3c71c08591
2 changed files with 101 additions and 69 deletions

View File

@@ -39,6 +39,7 @@ import { ChromecastSettingsMenu } from "@/components/chromecast/ChromecastSettin
import { useChromecastSegments } from "@/components/chromecast/hooks/useChromecastSegments";
import { Text } from "@/components/common/Text";
import { useCasting } from "@/hooks/useCasting";
import { useCastPlayerItem } from "@/hooks/useCastPlayerItem";
import { useCastSelection } from "@/hooks/useCastSelection";
import { useTrickplay } from "@/hooks/useTrickplay";
import { apiAtom, userAtom } from "@/providers/JellyfinProvider";
@@ -87,35 +88,12 @@ export default function CastingPlayerScreen() {
// Last stable playback position (seconds), for resuming across reloads.
const resumePositionRef = useRef(0);
// Fetch full item data from Jellyfin by ID
const [fetchedItem, setFetchedItem] = useState<BaseItemDto | null>(null);
useEffect(() => {
const controller = new AbortController();
const fetchItemData = async () => {
const itemId = mediaStatus?.mediaInfo?.contentId;
if (!itemId || !api || !user?.Id) return;
try {
const res = await getUserLibraryApi(api).getItem(
{ itemId, userId: user.Id },
{ signal: controller.signal },
);
if (!controller.signal.aborted) {
setFetchedItem(res.data);
}
} catch (error) {
if (error instanceof DOMException && error.name === "AbortError")
return;
console.error("[Casting Player] Failed to fetch item:", error);
}
};
fetchItemData();
return () => controller.abort();
}, [mediaStatus?.mediaInfo?.contentId, api, user?.Id]);
// Fetch full item data from Jellyfin by ID and derive the effective item
const { fetchedItem, currentItem } = useCastPlayerItem({
api,
user,
mediaStatus,
});
useEffect(() => {
// Sync refs whenever mediaStatus provides a new position
@@ -150,46 +128,6 @@ export default function CastingPlayerScreen() {
}
}, [mediaStatus?.streamPosition, mediaStatus?.playerState]);
// Extract item from customData, or use fetched item, or create a minimal fallback
const currentItem = useMemo(() => {
// Priority 1: Use fetched item from API (most reliable)
if (fetchedItem) {
return fetchedItem;
}
// Priority 2: Try customData from mediaStatus
const customData = mediaStatus?.mediaInfo?.customData as BaseItemDto | null;
if (
customData?.Type &&
(customData.ImageTags || customData.MediaSources || customData.Id)
) {
// Use customData if it has a real Type AND meaningful metadata
// (rules out placeholder objects that lack image tags, media sources, or an ID)
return customData;
}
// Priority 3: Create minimal fallback while loading
if (mediaStatus?.mediaInfo) {
const { contentId, metadata } = mediaStatus.mediaInfo;
// Derive type from metadata if available, otherwise omit to avoid
// misrepresenting episodes as movies
let metadataType: string | undefined;
if (metadata?.type === "movie") {
metadataType = "Movie";
} else if (metadata?.type === "tvShow") {
metadataType = "Episode";
}
return {
Id: contentId,
Name: metadata?.title || "Unknown",
...(metadataType ? { Type: metadataType } : {}),
ServerId: "",
} as BaseItemDto;
}
return null;
}, [fetchedItem, mediaStatus?.mediaInfo]);
// Derive state from raw Chromecast hooks
const progress = liveProgress; // Use live-updating progress
const duration = mediaStatus?.mediaInfo?.streamDuration ?? 0;