This commit is contained in:
Fredrik Burmester
2024-09-29 22:56:22 +02:00
parent 12cb6d4963
commit 9458d113de
8 changed files with 86 additions and 74 deletions

View File

@@ -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

View File

@@ -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>

View File

@@ -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();

BIN
bun.lockb

Binary file not shown.

View File

@@ -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>

View File

@@ -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",

View File

@@ -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;

View File

@@ -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",
};