mirror of
https://github.com/streamyfin/streamyfin.git
synced 2026-04-14 13:01:57 +01:00
wip
This commit is contained in:
@@ -1,51 +1,55 @@
|
||||
// hooks/useFileOpener.ts
|
||||
|
||||
import { usePlaySettings } from "@/providers/PlaySettingsProvider";
|
||||
import { writeToLog } from "@/utils/log";
|
||||
import { BaseItemDto } from "@jellyfin/sdk/lib/generated-client";
|
||||
import * as FileSystem from "expo-file-system";
|
||||
import { useRouter } from "expo-router";
|
||||
import { useCallback } from "react";
|
||||
import { Platform } from "react-native";
|
||||
|
||||
export const useFileOpener = () => {
|
||||
export const getDownloadedFileUrl = async (itemId: string): Promise<string> => {
|
||||
const directory = FileSystem.documentDirectory;
|
||||
|
||||
if (!directory) {
|
||||
throw new Error("Document directory is not available");
|
||||
}
|
||||
|
||||
if (!itemId) {
|
||||
throw new Error("Item ID is not available");
|
||||
}
|
||||
|
||||
const files = await FileSystem.readDirectoryAsync(directory);
|
||||
const path = itemId!;
|
||||
const matchingFile = files.find((file) => file.startsWith(path));
|
||||
|
||||
if (!matchingFile) {
|
||||
throw new Error(`No file found for item ${path}`);
|
||||
}
|
||||
|
||||
return `${directory}${matchingFile}`;
|
||||
};
|
||||
|
||||
export const useDownloadedFileOpener = () => {
|
||||
const router = useRouter();
|
||||
const { setPlayUrl, setOfflineSettings } = usePlaySettings();
|
||||
|
||||
const openFile = useCallback(async (item: BaseItemDto) => {
|
||||
const directory = FileSystem.documentDirectory;
|
||||
const openFile = useCallback(
|
||||
async (item: BaseItemDto) => {
|
||||
try {
|
||||
const url = await getDownloadedFileUrl(item.Id!);
|
||||
|
||||
if (!directory) {
|
||||
throw new Error("Document directory is not available");
|
||||
}
|
||||
setOfflineSettings({
|
||||
item,
|
||||
});
|
||||
setPlayUrl(url);
|
||||
|
||||
if (!item.Id) {
|
||||
throw new Error("Item ID is not available");
|
||||
}
|
||||
|
||||
try {
|
||||
const files = await FileSystem.readDirectoryAsync(directory);
|
||||
const path = item.Id!;
|
||||
const matchingFile = files.find((file) => file.startsWith(path));
|
||||
|
||||
if (!matchingFile) {
|
||||
throw new Error(`No file found for item ${path}`);
|
||||
// @ts-expect-error
|
||||
router.push("/player?offline=true&itemId=" + item.Id);
|
||||
} catch (error) {
|
||||
writeToLog("ERROR", "Error opening file", error);
|
||||
console.error("Error opening file:", error);
|
||||
}
|
||||
|
||||
const url = `${directory}${matchingFile}`;
|
||||
|
||||
setOfflineSettings({
|
||||
item,
|
||||
});
|
||||
setPlayUrl(url);
|
||||
|
||||
if (Platform.OS === "ios") router.push("/offline-vlc-player");
|
||||
else router.push("/offline-player");
|
||||
} catch (error) {
|
||||
writeToLog("ERROR", "Error opening file", error);
|
||||
console.error("Error opening file:", error);
|
||||
}
|
||||
}, []);
|
||||
},
|
||||
[setOfflineSettings, setPlayUrl, router]
|
||||
);
|
||||
|
||||
return { openFile };
|
||||
};
|
||||
|
||||
@@ -3,7 +3,10 @@ import { useAtom, useAtomValue } from "jotai";
|
||||
import AsyncStorage from "@react-native-async-storage/async-storage";
|
||||
import * as FileSystem from "expo-file-system";
|
||||
import { FFmpegKit, FFmpegKitConfig } from "ffmpeg-kit-react-native";
|
||||
import { BaseItemDto } from "@jellyfin/sdk/lib/generated-client/models";
|
||||
import {
|
||||
BaseItemDto,
|
||||
MediaSourceInfo,
|
||||
} from "@jellyfin/sdk/lib/generated-client/models";
|
||||
import { writeToLog } from "@/utils/log";
|
||||
import { useQueryClient } from "@tanstack/react-query";
|
||||
import { toast } from "sonner-native";
|
||||
@@ -21,22 +24,16 @@ import { apiAtom } from "@/providers/JellyfinProvider";
|
||||
* @param item - The BaseItemDto object representing the media item
|
||||
* @returns An object with remuxing-related functions
|
||||
*/
|
||||
export const useRemuxHlsToMp4 = (item: BaseItemDto) => {
|
||||
export const useRemuxHlsToMp4 = () => {
|
||||
const api = useAtomValue(apiAtom);
|
||||
const queryClient = useQueryClient();
|
||||
const { saveDownloadedItemInfo, setProcesses } = useDownload();
|
||||
const router = useRouter();
|
||||
const { saveImage } = useImageStorage();
|
||||
|
||||
if (!item.Id || !item.Name) {
|
||||
writeToLog("ERROR", "useRemuxHlsToMp4 ~ missing arguments");
|
||||
throw new Error("Item must have an Id and Name");
|
||||
}
|
||||
|
||||
const output = `${FileSystem.documentDirectory}${item.Id}.mp4`;
|
||||
|
||||
const startRemuxing = useCallback(
|
||||
async (url: string) => {
|
||||
async (item: BaseItemDto, url: string, mediaSource: MediaSourceInfo) => {
|
||||
const output = `${FileSystem.documentDirectory}${item.Id}.mp4`;
|
||||
if (!api) throw new Error("API is not defined");
|
||||
if (!item.Id) throw new Error("Item must have an Id");
|
||||
|
||||
@@ -74,13 +71,16 @@ export const useRemuxHlsToMp4 = (item: BaseItemDto) => {
|
||||
id: "",
|
||||
deviceId: "",
|
||||
inputUrl: "",
|
||||
item,
|
||||
itemId: item.Id,
|
||||
item: {
|
||||
item,
|
||||
mediaSource,
|
||||
},
|
||||
itemId: item.Id!,
|
||||
outputPath: "",
|
||||
progress: 0,
|
||||
status: "downloading",
|
||||
timestamp: new Date(),
|
||||
} as JobStatus,
|
||||
},
|
||||
]);
|
||||
|
||||
FFmpegKitConfig.enableStatisticsCallback((statistics) => {
|
||||
@@ -119,7 +119,7 @@ export const useRemuxHlsToMp4 = (item: BaseItemDto) => {
|
||||
|
||||
if (returnCode.isValueSuccess()) {
|
||||
if (!item) throw new Error("Item is undefined");
|
||||
await saveDownloadedItemInfo(item);
|
||||
await saveDownloadedItemInfo(item, mediaSource);
|
||||
toast.success("Download completed");
|
||||
writeToLog(
|
||||
"INFO",
|
||||
@@ -134,7 +134,7 @@ export const useRemuxHlsToMp4 = (item: BaseItemDto) => {
|
||||
"ERROR",
|
||||
`useRemuxHlsToMp4 ~ remuxing failed for item: ${item.Name}`
|
||||
);
|
||||
reject(new Error("Remuxing failed")); // Reject the promise on error
|
||||
reject(new Error("Remuxing failed"));
|
||||
} else if (returnCode.isValueCancel()) {
|
||||
writeToLog(
|
||||
"INFO",
|
||||
@@ -163,15 +163,13 @@ export const useRemuxHlsToMp4 = (item: BaseItemDto) => {
|
||||
throw error; // Re-throw the error to propagate it to the caller
|
||||
}
|
||||
},
|
||||
[output, item]
|
||||
[]
|
||||
);
|
||||
|
||||
const cancelRemuxing = useCallback(() => {
|
||||
FFmpegKit.cancel();
|
||||
setProcesses((prev) => {
|
||||
return prev.filter((process) => process.itemId !== item.Id);
|
||||
});
|
||||
}, [item.Name]);
|
||||
setProcesses([]);
|
||||
}, []);
|
||||
|
||||
return { startRemuxing, cancelRemuxing };
|
||||
};
|
||||
|
||||
@@ -15,6 +15,7 @@ interface UseWebSocketProps {
|
||||
pauseVideo: () => void;
|
||||
playVideo: () => void;
|
||||
stopPlayback: () => void;
|
||||
offline?: boolean;
|
||||
}
|
||||
|
||||
export const useWebSocket = ({
|
||||
@@ -22,6 +23,7 @@ export const useWebSocket = ({
|
||||
pauseVideo,
|
||||
playVideo,
|
||||
stopPlayback,
|
||||
offline = false,
|
||||
}: UseWebSocketProps) => {
|
||||
const router = useRouter();
|
||||
const user = useAtomValue(userAtom);
|
||||
@@ -38,7 +40,7 @@ export const useWebSocket = ({
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
if (!deviceId || !api?.accessToken) return;
|
||||
if (offline || !deviceId || !api?.accessToken) return;
|
||||
|
||||
const protocol = api?.basePath.includes("https") ? "wss" : "ws";
|
||||
|
||||
@@ -80,10 +82,10 @@ export const useWebSocket = ({
|
||||
}
|
||||
newWebSocket.close();
|
||||
};
|
||||
}, [api, deviceId, user]);
|
||||
}, [api, deviceId, user, offline]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!ws) return;
|
||||
if (offline || !ws) return;
|
||||
|
||||
ws.onmessage = (e) => {
|
||||
const json = JSON.parse(e.data);
|
||||
@@ -106,7 +108,7 @@ export const useWebSocket = ({
|
||||
Alert.alert("Message from server: " + title, body);
|
||||
}
|
||||
};
|
||||
}, [ws, stopPlayback, playVideo, pauseVideo, isPlaying, router]);
|
||||
}, [ws, stopPlayback, playVideo, pauseVideo, isPlaying, router, offline]);
|
||||
|
||||
return { isConnected };
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user