mirror of
https://github.com/streamyfin/streamyfin.git
synced 2026-06-02 03:58:36 +01:00
wip
This commit is contained in:
@@ -3,16 +3,18 @@ import { getItemsApi } from "@jellyfin/sdk/lib/utils/api/items-api";
|
||||
import { BaseItemDto } from "@jellyfin/sdk/lib/generated-client";
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
import { CurrentlyPlayingState } from "@/providers/PlaybackProvider";
|
||||
import { useAtom } from "jotai";
|
||||
import { apiAtom } from "@/providers/JellyfinProvider";
|
||||
|
||||
interface AdjacentEpisodesProps {
|
||||
api: Api | null;
|
||||
currentlyPlaying?: CurrentlyPlayingState | null;
|
||||
}
|
||||
|
||||
export const useAdjacentEpisodes = ({
|
||||
api,
|
||||
currentlyPlaying,
|
||||
}: AdjacentEpisodesProps) => {
|
||||
const [api] = useAtom(apiAtom);
|
||||
|
||||
const { data: previousItem } = useQuery({
|
||||
queryKey: [
|
||||
"previousItem",
|
||||
|
||||
25
hooks/useControlsVisibility.ts
Normal file
25
hooks/useControlsVisibility.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
import { useRef, useCallback, useState, useEffect } from "react";
|
||||
|
||||
export const useControlsVisibility = (timeout: number = 3000) => {
|
||||
const [isVisible, setIsVisible] = useState(true);
|
||||
const hideControlsTimerRef = useRef<NodeJS.Timeout | null>(null);
|
||||
|
||||
const showControls = useCallback(() => {
|
||||
setIsVisible(true);
|
||||
if (hideControlsTimerRef.current) {
|
||||
clearTimeout(hideControlsTimerRef.current);
|
||||
}
|
||||
hideControlsTimerRef.current = setTimeout(() => {
|
||||
setIsVisible(false);
|
||||
}, timeout);
|
||||
}, [timeout]);
|
||||
|
||||
const hideControls = useCallback(() => {
|
||||
setIsVisible(false);
|
||||
if (hideControlsTimerRef.current) {
|
||||
clearTimeout(hideControlsTimerRef.current);
|
||||
}
|
||||
}, []);
|
||||
|
||||
return { isVisible, showControls, hideControls };
|
||||
};
|
||||
@@ -1,19 +1,25 @@
|
||||
// hooks/useTrickplay.ts
|
||||
|
||||
import { useState, useCallback } from "react";
|
||||
import { useState, useCallback, useMemo } from "react";
|
||||
import { Api } from "@jellyfin/sdk";
|
||||
import { SharedValue } from "react-native-reanimated";
|
||||
import { CurrentlyPlayingState } from "@/providers/PlaybackProvider";
|
||||
import { useAtom } from "jotai";
|
||||
import { apiAtom } from "@/providers/JellyfinProvider";
|
||||
|
||||
interface TrickplayData {
|
||||
Interval?: number;
|
||||
TileWidth?: number;
|
||||
TileHeight?: number;
|
||||
Height?: number;
|
||||
Width?: number;
|
||||
ThumbnailCount?: number;
|
||||
}
|
||||
|
||||
interface TrickplayInfo {
|
||||
data: {
|
||||
Interval?: number;
|
||||
TileWidth?: number;
|
||||
TileHeight?: number;
|
||||
Height?: number;
|
||||
Width?: number;
|
||||
ThumbnailCount?: number;
|
||||
};
|
||||
resolution?: string;
|
||||
resolution: string;
|
||||
aspectRatio: number;
|
||||
data: TrickplayData;
|
||||
}
|
||||
|
||||
interface TrickplayUrl {
|
||||
@@ -22,33 +28,47 @@ interface TrickplayUrl {
|
||||
url: string;
|
||||
}
|
||||
|
||||
export const useTrickplay = () => {
|
||||
export const useTrickplay = (
|
||||
currentlyPlaying?: CurrentlyPlayingState | null
|
||||
) => {
|
||||
const [api] = useAtom(apiAtom);
|
||||
const [trickPlayUrl, setTrickPlayUrl] = useState<TrickplayUrl | null>(null);
|
||||
|
||||
const trickplayInfo = useMemo(() => {
|
||||
if (!currentlyPlaying?.item.Id || !currentlyPlaying?.item.Trickplay) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const mediaSourceId = currentlyPlaying.item.Id;
|
||||
const trickplayData = currentlyPlaying.item.Trickplay[mediaSourceId];
|
||||
|
||||
if (!trickplayData) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Get the first available resolution
|
||||
const firstResolution = Object.keys(trickplayData)[0];
|
||||
return firstResolution
|
||||
? {
|
||||
resolution: firstResolution,
|
||||
aspectRatio:
|
||||
trickplayData[firstResolution].Width! /
|
||||
trickplayData[firstResolution].Height!,
|
||||
data: trickplayData[firstResolution],
|
||||
}
|
||||
: null;
|
||||
}, [currentlyPlaying]);
|
||||
|
||||
const calculateTrickplayUrl = useCallback(
|
||||
(
|
||||
info: TrickplayInfo | null,
|
||||
progress: SharedValue<number>,
|
||||
api: Api | null,
|
||||
id: string
|
||||
) => {
|
||||
if (!info || !id || !api) {
|
||||
(progress: SharedValue<number>) => {
|
||||
if (!trickplayInfo || !api || !currentlyPlaying?.item.Id) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const { data, resolution } = info;
|
||||
const { Interval, TileWidth, TileHeight, Height, Width, ThumbnailCount } =
|
||||
data;
|
||||
const { data, resolution } = trickplayInfo;
|
||||
const { Interval, TileWidth, TileHeight } = data;
|
||||
|
||||
if (
|
||||
!Interval ||
|
||||
!TileWidth ||
|
||||
!TileHeight ||
|
||||
!Height ||
|
||||
!Width ||
|
||||
!ThumbnailCount ||
|
||||
!resolution
|
||||
) {
|
||||
if (!Interval || !TileWidth || !TileHeight || !resolution) {
|
||||
throw new Error("Invalid trickplay data");
|
||||
}
|
||||
|
||||
@@ -67,14 +87,14 @@ export const useTrickplay = () => {
|
||||
const newTrickPlayUrl = {
|
||||
x: rowInTile,
|
||||
y: colInTile,
|
||||
url: `${api.basePath}/Videos/${id}/Trickplay/${resolution}/${tileIndex}.jpg?api_key=${api.accessToken}`,
|
||||
url: `${api.basePath}/Videos/${currentlyPlaying.item.Id}/Trickplay/${resolution}/${tileIndex}.jpg?api_key=${api.accessToken}`,
|
||||
};
|
||||
|
||||
setTrickPlayUrl(newTrickPlayUrl);
|
||||
return newTrickPlayUrl;
|
||||
},
|
||||
[]
|
||||
[trickplayInfo, currentlyPlaying, api]
|
||||
);
|
||||
|
||||
return { trickPlayUrl, calculateTrickplayUrl };
|
||||
return { trickPlayUrl, calculateTrickplayUrl, trickplayInfo };
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user