import { Text } from "@/components/common/Text"; import { useSessions, useSessionsProps } from "@/hooks/useSessions"; import { FlashList } from "@shopify/flash-list"; import { useTranslation } from "react-i18next"; import { View } from "react-native"; import { Loader } from "@/components/Loader"; import { SessionInfoDto } from "@jellyfin/sdk/lib/generated-client"; import { useAtomValue } from "jotai"; import { apiAtom } from "@/providers/JellyfinProvider"; import Poster from "@/components/posters/Poster"; import { getPrimaryImageUrl } from "@/utils/jellyfin/image/getPrimaryImageUrl"; import { useInterval } from "@/hooks/useInterval"; import React, { useEffect, useMemo, useState } from "react"; import { formatTimeString } from "@/utils/time"; import { formatBitrate } from "@/utils/bitrate"; import { Ionicons, Entypo, AntDesign, MaterialCommunityIcons, } from "@expo/vector-icons"; import { Badge } from "@/components/Badge"; export default function page() { const { sessions, isLoading } = useSessions({} as useSessionsProps); const { t } = useTranslation(); if (isLoading) return ( ); if (!sessions || sessions.length == 0) return ( {t("home.sessions.no_active_sessions")} ); return ( } keyExtractor={(item) => item.Id || ""} estimatedItemSize={200} /> ); } interface SessionCardProps { session: SessionInfoDto; } const SessionCard = ({ session }: SessionCardProps) => { const api = useAtomValue(apiAtom); const [remainingTicks, setRemainingTicks] = useState(0); const tick = () => { if (session.PlayState?.IsPaused) return; setRemainingTicks(remainingTicks - 10000000); }; const getProgressPercentage = () => { if (!session.NowPlayingItem || !session.NowPlayingItem.RunTimeTicks) { return 0; } return Math.round( (100 / session.NowPlayingItem?.RunTimeTicks) * (session.NowPlayingItem?.RunTimeTicks - remainingTicks) ); }; useEffect(() => { const currentTime = session.PlayState?.PositionTicks; const duration = session.NowPlayingItem?.RunTimeTicks; if ( duration !== null && duration !== undefined && currentTime !== null && currentTime !== undefined ) { const remainingTimeTicks = duration - currentTime; setRemainingTicks(remainingTimeTicks); } }, [session]); useInterval(tick, 1000); return ( {session.NowPlayingItem?.Name} {!session.NowPlayingItem?.SeriesName && ( {session.NowPlayingItem?.ProductionYear} )} {session.NowPlayingItem?.SeriesName && ( {session.NowPlayingItem?.SeriesName} )} {session.UserName} {"\n"} {session.Client} {"\n"} {session.DeviceName} {!session.PlayState?.IsPaused ? ( ) : ( )} {formatTimeString(remainingTicks, "tick")} left ); }; interface TranscodingBadgesProps { properties: Array; } const TranscodingBadges = ({ properties = [] }: TranscodingBadgesProps) => { const icon = (val: string) => { switch (val) { case "bitrate": return ; break; case "codec": return ; break; case "videoRange": return ( ); break; case "resolution": return ; break; case "language": return ; break; case "audioChannels": return ; break; default: return ; } }; const formatVal = (key: String, val: any) => { switch (key) { case "bitrate": return formatBitrate(val); break; default: return val; } }; return Object.keys(properties) .filter( (key) => !(properties[key] === undefined || properties[key] === null) ) .map((key) => ( )); }; interface StreamProps { resolution: String | null | undefined; language: String | null | undefined; codec: String | null | undefined; bitrate: number | null | undefined; videoRange: String | null | undefined; audioChannels: String | null | undefined; } interface TranscodingStreamViewProps { title: String | undefined; value: String; isTranscoding: Boolean; transcodeValue: String | undefined | null; properties: Array; transcodeProperties: Array; } const TranscodingStreamView = ({ title, value, isTranscoding, transcodeValue, properties = [], transcodeProperties = [], }: TranscodingStreamViewProps) => { return ( {title} {isTranscoding && ( <> )} ); }; const TranscodingView = ({ session }: SessionCardProps) => { const videoStream = useMemo(() => { return session.NowPlayingItem?.MediaStreams?.filter( (s) => s.Type == "Video" )[0]; }, [session]); const audioStream = useMemo(() => { const index = session.PlayState?.AudioStreamIndex; return index !== null && index !== undefined ? session.NowPlayingItem?.MediaStreams?.[index] : undefined; }, [session.PlayState?.AudioStreamIndex]); const subtitleStream = useMemo(() => { const index = session.PlayState?.SubtitleStreamIndex; return index !== null && index !== undefined ? session.NowPlayingItem?.MediaStreams?.[index] : undefined; }, [session.PlayState?.SubtitleStreamIndex]); const isTranscoding = useMemo(() => { return session.PlayState?.PlayMethod == "Transcode"; }, [session.PlayState?.PlayMethod]); const videoStreamTitle = () => { return videoStream?.DisplayTitle?.split(" ")[0]; }; return ( {subtitleStream && ( <> )} ); };