mirror of
https://github.com/streamyfin/streamyfin.git
synced 2025-08-20 18:37:18 +02:00
wip
This commit is contained in:
2
app.json
2
app.json
@@ -19,7 +19,7 @@
|
||||
"infoPlist": {
|
||||
"NSCameraUsageDescription": "The app needs access to your camera to scan barcodes.",
|
||||
"NSMicrophoneUsageDescription": "The app needs access to your microphone.",
|
||||
"UIBackgroundModes": ["audio"],
|
||||
"UIBackgroundModes": ["audio", "fetch"],
|
||||
"NSLocalNetworkUsageDescription": "The app needs access to your local network to connect to your Jellyfin server.",
|
||||
"NSAppTransportSecurity": {
|
||||
"NSAllowsArbitraryLoads": true
|
||||
|
||||
@@ -2,7 +2,10 @@ import { Button } from "@/components/Button";
|
||||
import { Text } from "@/components/common/Text";
|
||||
import { ListItem } from "@/components/ListItem";
|
||||
import { SettingToggles } from "@/components/settings/SettingToggles";
|
||||
import { useDownload } from "@/providers/DownloadProvider";
|
||||
import {
|
||||
registerBackgroundFetchAsync,
|
||||
useDownload,
|
||||
} from "@/providers/DownloadProvider";
|
||||
import { apiAtom, useJellyfin, userAtom } from "@/providers/JellyfinProvider";
|
||||
import { clearLogs, readFromLog } from "@/utils/log";
|
||||
import { getQuickConnectApi } from "@jellyfin/sdk/lib/utils/api";
|
||||
@@ -66,6 +69,13 @@ export default function settings() {
|
||||
}}
|
||||
>
|
||||
<View className="p-4 flex flex-col gap-y-4">
|
||||
{/* <Button
|
||||
onPress={() => {
|
||||
registerBackgroundFetchAsync();
|
||||
}}
|
||||
>
|
||||
registerBackgroundFetchAsync
|
||||
</Button> */}
|
||||
<View>
|
||||
<Text className="font-bold text-lg mb-2">Information</Text>
|
||||
|
||||
|
||||
@@ -1,28 +1,27 @@
|
||||
import { FullScreenVideoPlayer } from "@/components/FullScreenVideoPlayer";
|
||||
import { DownloadProvider } from "@/providers/DownloadProvider";
|
||||
import { JellyfinProvider } from "@/providers/JellyfinProvider";
|
||||
import { JobQueueProvider } from "@/providers/JobQueueProvider";
|
||||
import { PlaybackProvider } from "@/providers/PlaybackProvider";
|
||||
import { orientationAtom } from "@/utils/atoms/orientation";
|
||||
import { useSettings } from "@/utils/atoms/settings";
|
||||
import { ActionSheetProvider } from "@expo/react-native-action-sheet";
|
||||
import { BottomSheetModalProvider } from "@gorhom/bottom-sheet";
|
||||
import { checkForExistingDownloads } from "@kesha-antonov/react-native-background-downloader";
|
||||
import { DarkTheme, ThemeProvider } from "@react-navigation/native";
|
||||
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
|
||||
import { useFonts } from "expo-font";
|
||||
import { useKeepAwake } from "expo-keep-awake";
|
||||
import { Stack, useRouter } from "expo-router";
|
||||
import * as Linking from "expo-linking";
|
||||
import { Stack } from "expo-router";
|
||||
import * as ScreenOrientation from "expo-screen-orientation";
|
||||
import * as SplashScreen from "expo-splash-screen";
|
||||
import { StatusBar } from "expo-status-bar";
|
||||
import { Provider as JotaiProvider, useAtom } from "jotai";
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
import { useEffect, useRef } from "react";
|
||||
import { AppState } from "react-native";
|
||||
import { GestureHandlerRootView } from "react-native-gesture-handler";
|
||||
import "react-native-reanimated";
|
||||
import * as Linking from "expo-linking";
|
||||
import { orientationAtom } from "@/utils/atoms/orientation";
|
||||
import { Toaster } from "sonner-native";
|
||||
import { checkForExistingDownloads } from "@kesha-antonov/react-native-background-downloader";
|
||||
import { AppState } from "react-native";
|
||||
import { DownloadProvider } from "@/providers/DownloadProvider";
|
||||
|
||||
SplashScreen.preventAutoHideAsync();
|
||||
|
||||
|
||||
@@ -36,8 +36,6 @@ export const SettingToggles: React.FC<Props> = ({ ...props }) => {
|
||||
const [marlinUrl, setMarlinUrl] = useState<string>("");
|
||||
const [optimizedVersionsServerUrl, setOptimizedVersionsServerUrl] =
|
||||
useState<string>("");
|
||||
const [optimizedVersionsAuthHeader, setOptimizedVersionsAuthHeader] =
|
||||
useState<string>("");
|
||||
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
@@ -571,65 +569,6 @@ export const SettingToggles: React.FC<Props> = ({ ...props }) => {
|
||||
</View>
|
||||
)}
|
||||
</View>
|
||||
|
||||
<View className="flex flex-col bg-neutral-900 px-4 py-4 w-full grow-0">
|
||||
<View className="flex flex-col shrink mb-2">
|
||||
<Text className="font-semibold">
|
||||
Optimized versions auth header
|
||||
</Text>
|
||||
<Text className="text-xs opacity-50">
|
||||
The auth header for the optimized versions server.
|
||||
</Text>
|
||||
</View>
|
||||
<View className="flex flex-col w-full">
|
||||
<Input
|
||||
placeholder="Optimized versions auth header..."
|
||||
defaultValue={
|
||||
settings.optimizedVersionsAuthHeader
|
||||
? settings.optimizedVersionsAuthHeader
|
||||
: ""
|
||||
}
|
||||
value={optimizedVersionsAuthHeader}
|
||||
keyboardType="url"
|
||||
returnKeyType="done"
|
||||
autoCapitalize="none"
|
||||
textContentType="URL"
|
||||
onChangeText={(text) => setOptimizedVersionsAuthHeader(text)}
|
||||
className="w-full"
|
||||
/>
|
||||
<Button
|
||||
color="purple"
|
||||
className=" h-12 w-full mt-2"
|
||||
onPress={() => {
|
||||
updateSettings({
|
||||
optimizedVersionsAuthHeader,
|
||||
});
|
||||
}}
|
||||
>
|
||||
Save
|
||||
</Button>
|
||||
</View>
|
||||
|
||||
{settings.optimizedVersionsAuthHeader && (
|
||||
<View className="p-4 bg-neutral-800 rounded-xl mt-2">
|
||||
<Text className="" selectable>
|
||||
{settings.optimizedVersionsAuthHeader}
|
||||
</Text>
|
||||
</View>
|
||||
)}
|
||||
<Button
|
||||
color="red"
|
||||
className="mt-2"
|
||||
onPress={() => {
|
||||
updateSettings({
|
||||
optimizedVersionsAuthHeader: null,
|
||||
optimizedVersionsServerUrl: null,
|
||||
});
|
||||
}}
|
||||
>
|
||||
Reset
|
||||
</Button>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
"@types/uuid": "^10.0.0",
|
||||
"axios": "^1.7.7",
|
||||
"expo": "~51.0.34",
|
||||
"expo-background-fetch": "~12.0.1",
|
||||
"expo-blur": "~13.0.2",
|
||||
"expo-build-properties": "~0.12.5",
|
||||
"expo-constants": "~16.0.2",
|
||||
@@ -50,6 +51,7 @@
|
||||
"expo-splash-screen": "~0.27.6",
|
||||
"expo-status-bar": "~1.12.1",
|
||||
"expo-system-ui": "~3.0.7",
|
||||
"expo-task-manager": "~11.8.2",
|
||||
"expo-updates": "~0.25.25",
|
||||
"expo-web-browser": "~13.0.3",
|
||||
"ffmpeg-kit-react-native": "^6.0.2",
|
||||
|
||||
@@ -26,6 +26,8 @@ import React, {
|
||||
} from "react";
|
||||
import { toast } from "sonner-native";
|
||||
import { apiAtom } from "./JellyfinProvider";
|
||||
import * as BackgroundFetch from "expo-background-fetch";
|
||||
import * as TaskManager from "expo-task-manager";
|
||||
|
||||
export type ProcessItem = {
|
||||
id: string;
|
||||
@@ -42,8 +44,33 @@ export type ProcessItem = {
|
||||
| "queued";
|
||||
};
|
||||
|
||||
export const BACKGROUND_FETCH_TASK = "background-fetch";
|
||||
|
||||
TaskManager.defineTask(BACKGROUND_FETCH_TASK, async () => {
|
||||
const now = Date.now();
|
||||
|
||||
console.log(
|
||||
`Got background fetch call at date: ${new Date(now).toISOString()}`
|
||||
);
|
||||
|
||||
// Be sure to return the successful result type!
|
||||
return BackgroundFetch.BackgroundFetchResult.NewData;
|
||||
});
|
||||
|
||||
const STORAGE_KEY = "runningProcesses";
|
||||
|
||||
export async function registerBackgroundFetchAsync() {
|
||||
return BackgroundFetch.registerTaskAsync(BACKGROUND_FETCH_TASK, {
|
||||
minimumInterval: 60 * 15, // 1 minutes
|
||||
stopOnTerminate: false, // android only,
|
||||
startOnBoot: true, // android only
|
||||
});
|
||||
}
|
||||
|
||||
export async function unregisterBackgroundFetchAsync() {
|
||||
return BackgroundFetch.unregisterTaskAsync(BACKGROUND_FETCH_TASK);
|
||||
}
|
||||
|
||||
const DownloadContext = createContext<ReturnType<
|
||||
typeof useDownloadProvider
|
||||
> | null>(null);
|
||||
@@ -66,6 +93,9 @@ function useDownloadProvider() {
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
// Check background task status
|
||||
checkStatusAsync();
|
||||
|
||||
// Load initial processes state from AsyncStorage
|
||||
const loadInitialProcesses = async () => {
|
||||
const storedProcesses = await readProcesses();
|
||||
@@ -74,6 +104,40 @@ function useDownloadProvider() {
|
||||
loadInitialProcesses();
|
||||
}, []);
|
||||
|
||||
/********************
|
||||
* Background task
|
||||
*******************/
|
||||
const [isRegistered, setIsRegistered] = useState(false);
|
||||
const [status, setStatus] =
|
||||
useState<BackgroundFetch.BackgroundFetchStatus | null>(null);
|
||||
|
||||
const checkStatusAsync = async () => {
|
||||
const status = await BackgroundFetch.getStatusAsync();
|
||||
const isRegistered = await TaskManager.isTaskRegisteredAsync(
|
||||
BACKGROUND_FETCH_TASK
|
||||
);
|
||||
setStatus(status);
|
||||
setIsRegistered(isRegistered);
|
||||
|
||||
console.log("Background fetch status:", status);
|
||||
console.log("Background fetch task registered:", isRegistered);
|
||||
};
|
||||
|
||||
const toggleFetchTask = async () => {
|
||||
if (isRegistered) {
|
||||
console.log("Unregistering background fetch task");
|
||||
await unregisterBackgroundFetchAsync();
|
||||
} else {
|
||||
console.log("Registering background fetch task");
|
||||
await registerBackgroundFetchAsync();
|
||||
}
|
||||
|
||||
checkStatusAsync();
|
||||
};
|
||||
/**********************
|
||||
**********************
|
||||
*********************/
|
||||
|
||||
const clearProcesses = useCallback(async () => {
|
||||
await AsyncStorage.removeItem(STORAGE_KEY);
|
||||
setProcesses([]);
|
||||
@@ -129,7 +193,7 @@ function useDownloadProvider() {
|
||||
})
|
||||
.begin(() => {
|
||||
toast.info(`Download started for ${process.item.Name}`);
|
||||
updateProcess(process.id, { state: "downloading" });
|
||||
updateProcess(process.id, { state: "downloading", progress: 0 });
|
||||
})
|
||||
.progress((data) => {
|
||||
const percent = (data.bytesDownloaded / data.bytesTotal) * 100;
|
||||
|
||||
@@ -73,7 +73,6 @@ export type Settings = {
|
||||
forwardSkipTime: number;
|
||||
rewindSkipTime: number;
|
||||
optimizedVersionsServerUrl?: string | null;
|
||||
optimizedVersionsAuthHeader?: string | null;
|
||||
downloadMethod?: "optimized" | "remux";
|
||||
};
|
||||
/**
|
||||
@@ -110,7 +109,6 @@ const loadSettings = async (): Promise<Settings> => {
|
||||
forwardSkipTime: 30,
|
||||
rewindSkipTime: 10,
|
||||
optimizedVersionsServerUrl: null,
|
||||
optimizedVersionsAuthHeader: null,
|
||||
downloadMethod: "remux",
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user