mirror of
https://github.com/streamyfin/streamyfin.git
synced 2026-01-15 23:59:08 +00:00
chore: Apply linting rules and add git hok (#611)
Co-authored-by: Fredrik Burmester <fredrik.burmester@gmail.com>
This commit is contained in:
@@ -7,14 +7,14 @@ import { getItemImage } from "@/utils/getItemImage";
|
||||
import { useLog, writeToLog } from "@/utils/log";
|
||||
import { storage } from "@/utils/mmkv";
|
||||
import {
|
||||
type JobStatus,
|
||||
cancelAllJobs,
|
||||
cancelJobById,
|
||||
deleteDownloadItemInfoFromDiskTmp,
|
||||
getAllJobsByDeviceId,
|
||||
getDownloadItemInfoFromDiskTmp,
|
||||
JobStatus,
|
||||
} from "@/utils/optimize-server";
|
||||
import {
|
||||
import type {
|
||||
BaseItemDto,
|
||||
MediaSourceInfo,
|
||||
} from "@jellyfin/sdk/lib/generated-client/models";
|
||||
@@ -23,11 +23,12 @@ import { focusManager, useQuery, useQueryClient } from "@tanstack/react-query";
|
||||
import axios from "axios";
|
||||
import * as Application from "expo-application";
|
||||
import * as FileSystem from "expo-file-system";
|
||||
import { FileInfo } from "expo-file-system";
|
||||
import type { FileInfo } from "expo-file-system";
|
||||
import Notifications from "expo-notifications";
|
||||
import { useRouter } from "expo-router";
|
||||
import { atom, useAtom } from "jotai";
|
||||
import React, {
|
||||
import type React from "react";
|
||||
import {
|
||||
createContext,
|
||||
useCallback,
|
||||
useContext,
|
||||
@@ -35,7 +36,7 @@ import React, {
|
||||
useMemo,
|
||||
} from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { AppState, AppStateStatus, Platform } from "react-native";
|
||||
import { AppState, type AppStateStatus, Platform } from "react-native";
|
||||
import { toast } from "sonner-native";
|
||||
import { apiAtom } from "./JellyfinProvider";
|
||||
|
||||
@@ -113,12 +114,12 @@ function useDownloadProvider() {
|
||||
.filter((p) => jobs.some((j) => j.id === p.id));
|
||||
|
||||
const updatedProcesses = jobs.filter(
|
||||
(j) => !downloadingProcesses.some((p) => p.id === j.id)
|
||||
(j) => !downloadingProcesses.some((p) => p.id === j.id),
|
||||
);
|
||||
|
||||
setProcesses([...updatedProcesses, ...downloadingProcesses]);
|
||||
|
||||
for (let job of jobs) {
|
||||
for (const job of jobs) {
|
||||
const process = processes.find((p) => p.id === job.id);
|
||||
if (
|
||||
process &&
|
||||
@@ -140,7 +141,7 @@ function useDownloadProvider() {
|
||||
toast.dismiss();
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
);
|
||||
Notifications.scheduleNotificationAsync({
|
||||
content: {
|
||||
@@ -188,7 +189,7 @@ function useDownloadProvider() {
|
||||
console.error(error);
|
||||
}
|
||||
},
|
||||
[settings?.optimizedVersionsServerUrl, authHeader]
|
||||
[settings?.optimizedVersionsServerUrl, authHeader],
|
||||
);
|
||||
|
||||
const APP_CACHE_DOWNLOAD_DIRECTORY = `${FileSystem.cacheDirectory}${Application.applicationId}/Downloads/`;
|
||||
@@ -206,8 +207,8 @@ function useDownloadProvider() {
|
||||
status: "downloading",
|
||||
progress: 0,
|
||||
}
|
||||
: p
|
||||
)
|
||||
: p,
|
||||
),
|
||||
);
|
||||
|
||||
BackGroundDownloader?.setConfig({
|
||||
@@ -230,7 +231,7 @@ function useDownloadProvider() {
|
||||
toast.dismiss();
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
const baseDirectory = FileSystem.documentDirectory;
|
||||
@@ -250,8 +251,8 @@ function useDownloadProvider() {
|
||||
status: "downloading",
|
||||
progress: 0,
|
||||
}
|
||||
: p
|
||||
)
|
||||
: p,
|
||||
),
|
||||
);
|
||||
})
|
||||
.progress((data) => {
|
||||
@@ -265,14 +266,14 @@ function useDownloadProvider() {
|
||||
status: "downloading",
|
||||
progress: percent,
|
||||
}
|
||||
: p
|
||||
)
|
||||
: p,
|
||||
),
|
||||
);
|
||||
})
|
||||
.done(async (doneHandler) => {
|
||||
await saveDownloadedItemInfo(
|
||||
process.item,
|
||||
doneHandler.bytesDownloaded
|
||||
doneHandler.bytesDownloaded,
|
||||
);
|
||||
toast.success(
|
||||
t("home.downloads.toasts.download_completed_for_item", {
|
||||
@@ -287,7 +288,7 @@ function useDownloadProvider() {
|
||||
toast.dismiss();
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
);
|
||||
setTimeout(() => {
|
||||
BackGroundDownloader.completeHandler(process.id);
|
||||
@@ -308,7 +309,7 @@ function useDownloadProvider() {
|
||||
t("home.downloads.toasts.download_failed_for_item", {
|
||||
item: process.item.Name,
|
||||
error: errorMsg,
|
||||
})
|
||||
}),
|
||||
);
|
||||
writeToLog("ERROR", `Download failed for ${process.item.Name}`, {
|
||||
error,
|
||||
@@ -323,7 +324,7 @@ function useDownloadProvider() {
|
||||
});
|
||||
});
|
||||
},
|
||||
[queryClient, settings?.optimizedVersionsServerUrl, authHeader]
|
||||
[queryClient, settings?.optimizedVersionsServerUrl, authHeader],
|
||||
);
|
||||
|
||||
const startBackgroundDownload = useCallback(
|
||||
@@ -359,7 +360,7 @@ function useDownloadProvider() {
|
||||
"Content-Type": "application/json",
|
||||
Authorization: authHeader,
|
||||
},
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
if (response.status !== 201) {
|
||||
@@ -378,7 +379,7 @@ function useDownloadProvider() {
|
||||
toast.dismiss();
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
);
|
||||
} catch (error) {
|
||||
writeToLog("ERROR", "Error in startBackgroundDownload", error);
|
||||
@@ -394,13 +395,13 @@ function useDownloadProvider() {
|
||||
t("home.downloads.toasts.failed_to_start_download_for_item", {
|
||||
item: item.Name,
|
||||
message: error.message,
|
||||
})
|
||||
}),
|
||||
);
|
||||
if (error.response) {
|
||||
toast.error(
|
||||
t("home.downloads.toasts.server_responded_with_status", {
|
||||
statusCode: error.response.status,
|
||||
})
|
||||
}),
|
||||
);
|
||||
} else if (error.request) {
|
||||
t("home.downloads.toasts.no_response_received_from_server");
|
||||
@@ -412,13 +413,13 @@ function useDownloadProvider() {
|
||||
toast.error(
|
||||
t(
|
||||
"home.downloads.toasts.failed_to_start_download_for_item_unexpected_error",
|
||||
{ item: item.Name }
|
||||
)
|
||||
{ item: item.Name },
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
},
|
||||
[settings?.optimizedVersionsServerUrl, authHeader]
|
||||
[settings?.optimizedVersionsServerUrl, authHeader],
|
||||
);
|
||||
|
||||
const deleteAllFiles = async (): Promise<void> => {
|
||||
@@ -431,24 +432,24 @@ function useDownloadProvider() {
|
||||
.then(() =>
|
||||
toast.success(
|
||||
t(
|
||||
"home.downloads.toasts.all_files_folders_and_jobs_deleted_successfully"
|
||||
)
|
||||
)
|
||||
"home.downloads.toasts.all_files_folders_and_jobs_deleted_successfully",
|
||||
),
|
||||
),
|
||||
)
|
||||
.catch((reason) => {
|
||||
console.error("Failed to delete all files, folders, and jobs:", reason);
|
||||
toast.error(
|
||||
t(
|
||||
"home.downloads.toasts.an_error_occured_while_deleting_files_and_jobs"
|
||||
)
|
||||
"home.downloads.toasts.an_error_occured_while_deleting_files_and_jobs",
|
||||
),
|
||||
);
|
||||
});
|
||||
};
|
||||
|
||||
const forEveryDocumentDirFile = async (
|
||||
includeMMKV: boolean = true,
|
||||
includeMMKV = true,
|
||||
ignoreList: string[] = [],
|
||||
callback: (file: FileInfo) => void
|
||||
callback: (file: FileInfo) => void,
|
||||
) => {
|
||||
const baseDirectory = FileSystem.documentDirectory;
|
||||
if (!baseDirectory) {
|
||||
@@ -553,7 +554,7 @@ function useDownloadProvider() {
|
||||
} catch (error) {
|
||||
console.error(
|
||||
`Failed to delete file and storage entry for ID ${id}:`,
|
||||
error
|
||||
error,
|
||||
);
|
||||
}
|
||||
};
|
||||
@@ -563,17 +564,17 @@ function useDownloadProvider() {
|
||||
items.map((i) => {
|
||||
if (i.Id) return deleteFile(i.Id);
|
||||
return;
|
||||
})
|
||||
}),
|
||||
).then(() => successHapticFeedback());
|
||||
};
|
||||
|
||||
const cleanCacheDirectory = async () => {
|
||||
const cacheDir = await FileSystem.getInfoAsync(
|
||||
APP_CACHE_DOWNLOAD_DIRECTORY
|
||||
APP_CACHE_DOWNLOAD_DIRECTORY,
|
||||
);
|
||||
if (cacheDir.exists) {
|
||||
const cachedFiles = await FileSystem.readDirectoryAsync(
|
||||
APP_CACHE_DOWNLOAD_DIRECTORY
|
||||
APP_CACHE_DOWNLOAD_DIRECTORY,
|
||||
);
|
||||
let position = 0;
|
||||
const batchSize = 3;
|
||||
@@ -584,14 +585,14 @@ function useDownloadProvider() {
|
||||
await Promise.all(
|
||||
itemsForBatch.map(async (file) => {
|
||||
const info = await FileSystem.getInfoAsync(
|
||||
`${APP_CACHE_DOWNLOAD_DIRECTORY}${file}`
|
||||
`${APP_CACHE_DOWNLOAD_DIRECTORY}${file}`,
|
||||
);
|
||||
if (info.exists) {
|
||||
await FileSystem.deleteAsync(info.uri, { idempotent: true });
|
||||
return Promise.resolve(file);
|
||||
}
|
||||
return Promise.reject();
|
||||
})
|
||||
}),
|
||||
);
|
||||
|
||||
position += batchSize;
|
||||
@@ -609,24 +610,24 @@ function useDownloadProvider() {
|
||||
promises.push(deleteFile(file.item.SeriesId));
|
||||
promises.push(deleteFile(file.item.Id!));
|
||||
return promises;
|
||||
}) || []
|
||||
}) || [],
|
||||
);
|
||||
};
|
||||
|
||||
const appSizeUsage = useMemo(async () => {
|
||||
const sizes: number[] =
|
||||
downloadedFiles?.map((d) => {
|
||||
return getDownloadedItemSize(d.item.Id!!);
|
||||
return getDownloadedItemSize(d.item.Id!);
|
||||
}) || [];
|
||||
|
||||
await forEveryDocumentDirFile(
|
||||
true,
|
||||
getAllDownloadedItems().map((d) => d.item.Id!!),
|
||||
getAllDownloadedItems().map((d) => d.item.Id!),
|
||||
(file) => {
|
||||
if (file.exists) {
|
||||
sizes.push(file.size);
|
||||
}
|
||||
}
|
||||
},
|
||||
).catch((e) => {
|
||||
console.error(e);
|
||||
});
|
||||
@@ -663,10 +664,10 @@ function useDownloadProvider() {
|
||||
}
|
||||
}
|
||||
|
||||
function saveDownloadedItemInfo(item: BaseItemDto, size: number = 0) {
|
||||
function saveDownloadedItemInfo(item: BaseItemDto, size = 0) {
|
||||
try {
|
||||
const downloadedItems = storage.getString("downloadedItems");
|
||||
let items: DownloadedItem[] = downloadedItems
|
||||
const items: DownloadedItem[] = downloadedItems
|
||||
? JSON.parse(downloadedItems)
|
||||
: [];
|
||||
|
||||
@@ -676,7 +677,7 @@ function useDownloadProvider() {
|
||||
|
||||
if (!data?.mediaSource)
|
||||
throw new Error(
|
||||
"Media source not found in tmp storage. Did you forget to save it before starting download?"
|
||||
"Media source not found in tmp storage. Did you forget to save it before starting download?",
|
||||
);
|
||||
|
||||
const newItem = { item, mediaSource: data.mediaSource };
|
||||
@@ -697,14 +698,14 @@ function useDownloadProvider() {
|
||||
} catch (error) {
|
||||
console.error(
|
||||
"Failed to save downloaded item information with media source:",
|
||||
error
|
||||
error,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function getDownloadedItemSize(itemId: string): number {
|
||||
const size = storage.getString("downloadedItemSize-" + itemId);
|
||||
return size ? parseInt(size) : 0;
|
||||
return size ? Number.parseInt(size) : 0;
|
||||
}
|
||||
|
||||
return {
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
import { storage } from "@/utils/mmkv";
|
||||
import { JobStatus } from "@/utils/optimize-server";
|
||||
import {
|
||||
import type { JobStatus } from "@/utils/optimize-server";
|
||||
import type {
|
||||
BaseItemDto,
|
||||
MediaSourceInfo,
|
||||
} from "@jellyfin/sdk/lib/generated-client/models";
|
||||
import * as Application from "expo-application";
|
||||
import * as FileSystem from "expo-file-system";
|
||||
import { atom, useAtom } from "jotai";
|
||||
import React, { createContext, useCallback, useContext, useMemo } from "react";
|
||||
import type React from "react";
|
||||
import { createContext, useCallback, useContext, useMemo } from "react";
|
||||
|
||||
export type DownloadedItem = {
|
||||
item: Partial<BaseItemDto>;
|
||||
@@ -38,7 +39,7 @@ function useDownloadProvider() {
|
||||
async (url: string, item: BaseItemDto, mediaSource: MediaSourceInfo) => {
|
||||
return null;
|
||||
},
|
||||
[]
|
||||
[],
|
||||
);
|
||||
|
||||
const deleteAllFiles = async (): Promise<void> => {};
|
||||
@@ -59,11 +60,11 @@ function useDownloadProvider() {
|
||||
return null;
|
||||
}
|
||||
|
||||
function saveDownloadedItemInfo(item: BaseItemDto, size: number = 0) {}
|
||||
function saveDownloadedItemInfo(item: BaseItemDto, size = 0) {}
|
||||
|
||||
function getDownloadedItemSize(itemId: string): number {
|
||||
const size = storage.getString("downloadedItemSize-" + itemId);
|
||||
return size ? parseInt(size) : 0;
|
||||
return size ? Number.parseInt(size) : 0;
|
||||
}
|
||||
|
||||
const APP_CACHE_DOWNLOAD_DIRECTORY = `${FileSystem.cacheDirectory}${Application.applicationId}/Downloads/`;
|
||||
|
||||
@@ -2,19 +2,21 @@ import "@/augmentations";
|
||||
import { useInterval } from "@/hooks/useInterval";
|
||||
import { JellyseerrApi, useJellyseerr } from "@/hooks/useJellyseerr";
|
||||
import { useSettings } from "@/utils/atoms/settings";
|
||||
import { writeErrorLog, writeInfoLog } from "@/utils/log";
|
||||
import { storage } from "@/utils/mmkv";
|
||||
import { store } from "@/utils/store";
|
||||
import { Api, Jellyfin } from "@jellyfin/sdk";
|
||||
import { UserDto } from "@jellyfin/sdk/lib/generated-client/models";
|
||||
import { type Api, Jellyfin } from "@jellyfin/sdk";
|
||||
import type { UserDto } from "@jellyfin/sdk/lib/generated-client/models";
|
||||
import { getUserApi } from "@jellyfin/sdk/lib/utils/api";
|
||||
import { useMutation, useQuery } from "@tanstack/react-query";
|
||||
import axios, { AxiosError } from "axios";
|
||||
import { router, useSegments } from "expo-router";
|
||||
import * as SplashScreen from "expo-splash-screen";
|
||||
import { atom, useAtom } from "jotai";
|
||||
import React, {
|
||||
import type React from "react";
|
||||
import {
|
||||
type ReactNode,
|
||||
createContext,
|
||||
ReactNode,
|
||||
useCallback,
|
||||
useContext,
|
||||
useEffect,
|
||||
@@ -25,7 +27,6 @@ import { useTranslation } from "react-i18next";
|
||||
import { Platform } from "react-native";
|
||||
import { getDeviceName } from "react-native-device-info";
|
||||
import uuid from "react-native-uuid";
|
||||
import {writeErrorLog, writeInfoLog} from "@/utils/log";
|
||||
|
||||
interface Server {
|
||||
address: string;
|
||||
@@ -45,7 +46,7 @@ interface JellyfinContextValue {
|
||||
}
|
||||
|
||||
const JellyfinContext = createContext<JellyfinContextValue | undefined>(
|
||||
undefined
|
||||
undefined,
|
||||
);
|
||||
|
||||
export const JellyfinProvider: React.FC<{ children: ReactNode }> = ({
|
||||
@@ -68,7 +69,7 @@ export const JellyfinProvider: React.FC<{ children: ReactNode }> = ({
|
||||
name: deviceName,
|
||||
id,
|
||||
},
|
||||
})
|
||||
}),
|
||||
);
|
||||
setDeviceId(id);
|
||||
})();
|
||||
@@ -104,7 +105,7 @@ export const JellyfinProvider: React.FC<{ children: ReactNode }> = ({
|
||||
null,
|
||||
{
|
||||
headers,
|
||||
}
|
||||
},
|
||||
);
|
||||
if (response?.status === 200) {
|
||||
setSecret(response?.data?.Secret);
|
||||
@@ -124,7 +125,7 @@ export const JellyfinProvider: React.FC<{ children: ReactNode }> = ({
|
||||
|
||||
try {
|
||||
const response = await api.axiosInstance.get(
|
||||
`${api.basePath}/QuickConnect/Connect?Secret=${secret}`
|
||||
`${api.basePath}/QuickConnect/Connect?Secret=${secret}`,
|
||||
);
|
||||
|
||||
if (response.status === 200) {
|
||||
@@ -138,7 +139,7 @@ export const JellyfinProvider: React.FC<{ children: ReactNode }> = ({
|
||||
},
|
||||
{
|
||||
headers,
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
const { AccessToken, User } = authResponse.data;
|
||||
@@ -167,7 +168,7 @@ export const JellyfinProvider: React.FC<{ children: ReactNode }> = ({
|
||||
await refreshStreamyfinPluginSettings();
|
||||
})();
|
||||
}, []);
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
store.set(apiAtom, api);
|
||||
}, [api]);
|
||||
@@ -176,9 +177,8 @@ export const JellyfinProvider: React.FC<{ children: ReactNode }> = ({
|
||||
useInterval(refreshStreamyfinPluginSettings, 60 * 5 * 1000); // 5 min
|
||||
|
||||
const discoverServers = async (url: string): Promise<Server[]> => {
|
||||
const servers = await jellyfin?.discovery.getRecommendedServerCandidates(
|
||||
url
|
||||
);
|
||||
const servers =
|
||||
await jellyfin?.discovery.getRecommendedServerCandidates(url);
|
||||
return servers?.map((server) => ({ address: server.address })) || [];
|
||||
};
|
||||
|
||||
@@ -193,7 +193,7 @@ export const JellyfinProvider: React.FC<{ children: ReactNode }> = ({
|
||||
},
|
||||
onSuccess: (_, server) => {
|
||||
const previousServers = JSON.parse(
|
||||
storage.getString("previousServers") || "[]"
|
||||
storage.getString("previousServers") || "[]",
|
||||
);
|
||||
const updatedServers = [
|
||||
server,
|
||||
@@ -201,7 +201,7 @@ export const JellyfinProvider: React.FC<{ children: ReactNode }> = ({
|
||||
];
|
||||
storage.set(
|
||||
"previousServers",
|
||||
JSON.stringify(updatedServers.slice(0, 5))
|
||||
JSON.stringify(updatedServers.slice(0, 5)),
|
||||
);
|
||||
},
|
||||
onError: (error) => {
|
||||
@@ -241,7 +241,7 @@ export const JellyfinProvider: React.FC<{ children: ReactNode }> = ({
|
||||
const recentPluginSettings = await refreshStreamyfinPluginSettings();
|
||||
if (recentPluginSettings?.jellyseerrServerUrl?.value) {
|
||||
const jellyseerrApi = new JellyseerrApi(
|
||||
recentPluginSettings.jellyseerrServerUrl.value
|
||||
recentPluginSettings.jellyseerrServerUrl.value,
|
||||
);
|
||||
await jellyseerrApi.test().then((result) => {
|
||||
if (result.isValid && result.requiresPass) {
|
||||
@@ -257,23 +257,23 @@ export const JellyfinProvider: React.FC<{ children: ReactNode }> = ({
|
||||
throw new Error(t("login.invalid_username_or_password"));
|
||||
case 403:
|
||||
throw new Error(
|
||||
t("login.user_does_not_have_permission_to_log_in")
|
||||
t("login.user_does_not_have_permission_to_log_in"),
|
||||
);
|
||||
case 408:
|
||||
throw new Error(
|
||||
t("login.server_is_taking_too_long_to_respond_try_again_later")
|
||||
t("login.server_is_taking_too_long_to_respond_try_again_later"),
|
||||
);
|
||||
case 429:
|
||||
throw new Error(
|
||||
t("login.server_received_too_many_requests_try_again_later")
|
||||
t("login.server_received_too_many_requests_try_again_later"),
|
||||
);
|
||||
case 500:
|
||||
throw new Error(t("login.there_is_a_server_error"));
|
||||
default:
|
||||
throw new Error(
|
||||
t(
|
||||
"login.an_unexpected_error_occured_did_you_enter_the_correct_url"
|
||||
)
|
||||
"login.an_unexpected_error_occured_did_you_enter_the_correct_url",
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -287,9 +287,12 @@ export const JellyfinProvider: React.FC<{ children: ReactNode }> = ({
|
||||
|
||||
const logoutMutation = useMutation({
|
||||
mutationFn: async () => {
|
||||
api?.delete(`/Streamyfin/device/${deviceId}`)
|
||||
.then(r => writeInfoLog("Deleted expo push token for device"))
|
||||
.catch(e => writeErrorLog(`Failed to delete expo push token for device`))
|
||||
api
|
||||
?.delete(`/Streamyfin/device/${deviceId}`)
|
||||
.then((r) => writeInfoLog("Deleted expo push token for device"))
|
||||
.catch((e) =>
|
||||
writeErrorLog(`Failed to delete expo push token for device`),
|
||||
);
|
||||
|
||||
storage.delete("token");
|
||||
setUser(null);
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import React, { createContext } from "react";
|
||||
import { useJobProcessor } from "@/utils/atoms/queue";
|
||||
import type React from "react";
|
||||
import { createContext } from "react";
|
||||
|
||||
const JobQueueContext = createContext(null);
|
||||
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
import { Bitrate } from "@/components/BitrateSelector";
|
||||
import type { Bitrate } from "@/components/BitrateSelector";
|
||||
import { settingsAtom } from "@/utils/atoms/settings";
|
||||
import { getStreamUrl } from "@/utils/jellyfin/media/getStreamUrl";
|
||||
import native from "@/utils/profiles/native";
|
||||
import {
|
||||
import type {
|
||||
BaseItemDto,
|
||||
MediaSourceInfo,
|
||||
} from "@jellyfin/sdk/lib/generated-client";
|
||||
import { getSessionApi } from "@jellyfin/sdk/lib/utils/api";
|
||||
import { useAtomValue } from "jotai";
|
||||
import React, {
|
||||
import type React from "react";
|
||||
import {
|
||||
createContext,
|
||||
useCallback,
|
||||
useContext,
|
||||
@@ -32,7 +33,7 @@ type PlaySettingsContextType = {
|
||||
dataOrUpdater:
|
||||
| PlaybackType
|
||||
| null
|
||||
| ((prev: PlaybackType | null) => PlaybackType | null)
|
||||
| ((prev: PlaybackType | null) => PlaybackType | null),
|
||||
) => Promise<{ url: string | null; sessionId: string | null } | null>;
|
||||
playUrl?: string | null;
|
||||
setPlayUrl: React.Dispatch<React.SetStateAction<string | null>>;
|
||||
@@ -41,7 +42,7 @@ type PlaySettingsContextType = {
|
||||
};
|
||||
|
||||
const PlaySettingsContext = createContext<PlaySettingsContextType | undefined>(
|
||||
undefined
|
||||
undefined,
|
||||
);
|
||||
|
||||
export const PlaySettingsProvider: React.FC<{ children: React.ReactNode }> = ({
|
||||
@@ -65,7 +66,7 @@ export const PlaySettingsProvider: React.FC<{ children: React.ReactNode }> = ({
|
||||
dataOrUpdater:
|
||||
| PlaybackType
|
||||
| null
|
||||
| ((prev: PlaybackType | null) => PlaybackType | null)
|
||||
| ((prev: PlaybackType | null) => PlaybackType | null),
|
||||
): Promise<{ url: string | null; sessionId: string | null } | null> => {
|
||||
if (!api || !user || !settings) {
|
||||
_setPlaySettings(null);
|
||||
@@ -109,7 +110,7 @@ export const PlaySettingsProvider: React.FC<{ children: React.ReactNode }> = ({
|
||||
return null;
|
||||
}
|
||||
},
|
||||
[api, user, settings, playSettings]
|
||||
[api, user, settings, playSettings],
|
||||
);
|
||||
|
||||
// useEffect(() => {
|
||||
@@ -153,7 +154,7 @@ export const usePlaySettings = () => {
|
||||
const context = useContext(PlaySettingsContext);
|
||||
if (context === undefined) {
|
||||
throw new Error(
|
||||
"usePlaySettings must be used within a PlaySettingsProvider"
|
||||
"usePlaySettings must be used within a PlaySettingsProvider",
|
||||
);
|
||||
}
|
||||
return context;
|
||||
|
||||
@@ -1,19 +1,16 @@
|
||||
import { apiAtom, getOrSetDeviceId } from "@/providers/JellyfinProvider";
|
||||
import { getSessionApi } from "@jellyfin/sdk/lib/utils/api";
|
||||
import { useAtomValue } from "jotai";
|
||||
import React, {
|
||||
createContext,
|
||||
useContext,
|
||||
useEffect,
|
||||
useState,
|
||||
ReactNode,
|
||||
type ReactNode,
|
||||
useMemo,
|
||||
useCallback,
|
||||
} from "react";
|
||||
import { AppState, AppStateStatus } from "react-native";
|
||||
import { useAtomValue } from "jotai";
|
||||
import {
|
||||
apiAtom,
|
||||
getOrSetDeviceId,
|
||||
} from "@/providers/JellyfinProvider";
|
||||
import { getSessionApi } from "@jellyfin/sdk/lib/utils/api";
|
||||
import { AppState, type AppStateStatus } from "react-native";
|
||||
|
||||
interface WebSocketProviderProps {
|
||||
children: ReactNode;
|
||||
@@ -121,7 +118,7 @@ export const WebSocketProvider = ({ children }: WebSocketProviderProps) => {
|
||||
|
||||
const subscription = AppState.addEventListener(
|
||||
"change",
|
||||
handleAppStateChange
|
||||
handleAppStateChange,
|
||||
);
|
||||
|
||||
return () => {
|
||||
@@ -141,7 +138,7 @@ export const useWebSocketContext = (): WebSocketContextType => {
|
||||
const context = useContext(WebSocketContext);
|
||||
if (!context) {
|
||||
throw new Error(
|
||||
"useWebSocketContext must be used within a WebSocketProvider"
|
||||
"useWebSocketContext must be used within a WebSocketProvider",
|
||||
);
|
||||
}
|
||||
return context;
|
||||
|
||||
Reference in New Issue
Block a user