mirror of
https://github.com/streamyfin/streamyfin.git
synced 2026-06-04 04:58:30 +01:00
Revert "Merge branch 'develop' into chore/expo-52"
This reverts commit933f3f2f7c, reversing changes made tof92fee4158.
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import {DownloadMethod, useSettings} from "@/utils/atoms/settings";
|
||||
import { useSettings } from "@/utils/atoms/settings";
|
||||
import { getOrSetDeviceId } from "@/utils/device";
|
||||
import { useLog, writeToLog } from "@/utils/log";
|
||||
import {
|
||||
@@ -48,9 +48,8 @@ import useImageStorage from "@/hooks/useImageStorage";
|
||||
import { storage } from "@/utils/mmkv";
|
||||
import useDownloadHelper from "@/utils/download";
|
||||
import { FileInfo } from "expo-file-system";
|
||||
import { useHaptic } from "@/hooks/useHaptic";
|
||||
import * as Haptics from "expo-haptics";
|
||||
import * as Application from "expo-application";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
export type DownloadedItem = {
|
||||
item: Partial<BaseItemDto>;
|
||||
@@ -69,7 +68,6 @@ const DownloadContext = createContext<ReturnType<
|
||||
|
||||
function useDownloadProvider() {
|
||||
const queryClient = useQueryClient();
|
||||
const { t } = useTranslation();
|
||||
const [settings] = useSettings();
|
||||
const router = useRouter();
|
||||
const [api] = useAtom(apiAtom);
|
||||
@@ -80,8 +78,6 @@ function useDownloadProvider() {
|
||||
|
||||
const [processes, setProcesses] = useAtom<JobStatus[]>(processesAtom);
|
||||
|
||||
const successHapticFeedback = useHaptic("success");
|
||||
|
||||
const authHeader = useMemo(() => {
|
||||
return api?.accessToken;
|
||||
}, [api]);
|
||||
@@ -108,7 +104,7 @@ function useDownloadProvider() {
|
||||
const url = settings?.optimizedVersionsServerUrl;
|
||||
|
||||
if (
|
||||
settings?.downloadMethod !== DownloadMethod.Optimized ||
|
||||
settings?.downloadMethod !== "optimized" ||
|
||||
!url ||
|
||||
!deviceId ||
|
||||
!authHeader
|
||||
@@ -141,9 +137,9 @@ function useDownloadProvider() {
|
||||
if (settings.autoDownload) {
|
||||
startDownload(job);
|
||||
} else {
|
||||
toast.info(t("home.downloads.toasts.item_is_ready_to_be_downloaded",{item: job.item.Name}), {
|
||||
toast.info(`${job.item.Name} is ready to be downloaded`, {
|
||||
action: {
|
||||
label: t("home.downloads.toasts.go_to_downloads"),
|
||||
label: "Go to downloads",
|
||||
onClick: () => {
|
||||
router.push("/downloads");
|
||||
toast.dismiss();
|
||||
@@ -168,7 +164,7 @@ function useDownloadProvider() {
|
||||
},
|
||||
staleTime: 0,
|
||||
refetchInterval: 2000,
|
||||
enabled: settings?.downloadMethod === DownloadMethod.Optimized,
|
||||
enabled: settings?.downloadMethod === "optimized",
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
@@ -226,9 +222,9 @@ function useDownloadProvider() {
|
||||
},
|
||||
});
|
||||
|
||||
toast.info(t("home.downloads.toasts.download_stated_for_item", {item: process.item.Name}), {
|
||||
toast.info(`Download started for ${process.item.Name}`, {
|
||||
action: {
|
||||
label: t("home.downloads.toasts.go_to_downloads"),
|
||||
label: "Go to downloads",
|
||||
onClick: () => {
|
||||
router.push("/downloads");
|
||||
toast.dismiss();
|
||||
@@ -277,10 +273,10 @@ function useDownloadProvider() {
|
||||
process.item,
|
||||
doneHandler.bytesDownloaded
|
||||
);
|
||||
toast.success(t("home.downloads.toasts.download_completed_for_item", {item: process.item.Name}), {
|
||||
toast.success(`Download completed for ${process.item.Name}`, {
|
||||
duration: 3000,
|
||||
action: {
|
||||
label: t("home.downloads.toasts.go_to_downloads"),
|
||||
label: "Go to downloads",
|
||||
onClick: () => {
|
||||
router.push("/downloads");
|
||||
toast.dismiss();
|
||||
@@ -302,7 +298,7 @@ function useDownloadProvider() {
|
||||
if (error.errorCode === 404) {
|
||||
errorMsg = "File not found on server";
|
||||
}
|
||||
toast.error(t("home.downloads.toasts.download_failed_for_item", {item: process.item.Name, error: errorMsg}));
|
||||
toast.error(`Download failed for ${process.item.Name} - ${errorMsg}`);
|
||||
writeToLog("ERROR", `Download failed for ${process.item.Name}`, {
|
||||
error,
|
||||
processDetails: {
|
||||
@@ -359,9 +355,9 @@ function useDownloadProvider() {
|
||||
throw new Error("Failed to start optimization job");
|
||||
}
|
||||
|
||||
toast.success(t("home.downloads.toasts.queued_item_for_optimization", {item: item.Name}), {
|
||||
toast.success(`Queued ${item.Name} for optimization`, {
|
||||
action: {
|
||||
label: t("home.downloads.toasts.go_to_downloads"),
|
||||
label: "Go to download",
|
||||
onClick: () => {
|
||||
router.push("/downloads");
|
||||
toast.dismiss();
|
||||
@@ -379,21 +375,21 @@ function useDownloadProvider() {
|
||||
headers: error.response?.headers,
|
||||
});
|
||||
toast.error(
|
||||
t("home.downloads.toasts.failed_to_start_download_for_item", {item: item.Name, message: error.message})
|
||||
`Failed to start download for ${item.Name}: ${error.message}`
|
||||
);
|
||||
if (error.response) {
|
||||
toast.error(
|
||||
t("home.downloads.toasts.server_responded_with_status", {statusCode: error.response.status})
|
||||
`Server responded with status ${error.response.status}`
|
||||
);
|
||||
} else if (error.request) {
|
||||
t("home.downloads.toasts.no_response_received_from_server");
|
||||
toast.error("No response received from server");
|
||||
} else {
|
||||
toast.error("Error setting up the request");
|
||||
}
|
||||
} else {
|
||||
console.error("Non-Axios error:", error);
|
||||
toast.error(
|
||||
t("home.downloads.toasts.failed_to_start_download_for_item_unexpected_error", {item: item.Name})
|
||||
`Failed to start download for ${item.Name}: Unexpected error`
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -409,11 +405,11 @@ function useDownloadProvider() {
|
||||
queryClient.invalidateQueries({ queryKey: ["downloadedItems"] }),
|
||||
])
|
||||
.then(() =>
|
||||
toast.success(t("home.downloads.toasts.all_files_folders_and_jobs_deleted_successfully"))
|
||||
toast.success("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"));
|
||||
toast.error("An error occurred while deleting files and jobs");
|
||||
});
|
||||
};
|
||||
|
||||
@@ -536,7 +532,9 @@ function useDownloadProvider() {
|
||||
if (i.Id) return deleteFile(i.Id);
|
||||
return;
|
||||
})
|
||||
).then(() => successHapticFeedback());
|
||||
).then(() =>
|
||||
Haptics.notificationAsync(Haptics.NotificationFeedbackType.Success)
|
||||
);
|
||||
};
|
||||
|
||||
const cleanCacheDirectory = async () => {
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import "@/augmentations";
|
||||
import { useInterval } from "@/hooks/useInterval";
|
||||
import { storage } from "@/utils/mmkv";
|
||||
import { Api, Jellyfin } from "@jellyfin/sdk";
|
||||
@@ -20,9 +19,7 @@ import React, {
|
||||
import { Platform } from "react-native";
|
||||
import uuid from "react-native-uuid";
|
||||
import { getDeviceName } from "react-native-device-info";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useSettings } from "@/utils/atoms/settings";
|
||||
import { JellyseerrApi, useJellyseerr } from "@/hooks/useJellyseerr";
|
||||
import { toast } from "sonner-native";
|
||||
|
||||
interface Server {
|
||||
address: string;
|
||||
@@ -51,8 +48,6 @@ export const JellyfinProvider: React.FC<{ children: ReactNode }> = ({
|
||||
const [jellyfin, setJellyfin] = useState<Jellyfin | undefined>(undefined);
|
||||
const [deviceId, setDeviceId] = useState<string | undefined>(undefined);
|
||||
|
||||
const { t } = useTranslation();
|
||||
|
||||
useEffect(() => {
|
||||
(async () => {
|
||||
const id = getOrSetDeviceId();
|
||||
@@ -60,7 +55,7 @@ export const JellyfinProvider: React.FC<{ children: ReactNode }> = ({
|
||||
setJellyfin(
|
||||
() =>
|
||||
new Jellyfin({
|
||||
clientInfo: { name: "Streamyfin", version: "0.25.0" },
|
||||
clientInfo: { name: "Streamyfin", version: "0.23.0" },
|
||||
deviceInfo: {
|
||||
name: deviceName,
|
||||
id,
|
||||
@@ -75,14 +70,6 @@ export const JellyfinProvider: React.FC<{ children: ReactNode }> = ({
|
||||
const [user, setUser] = useAtom(userAtom);
|
||||
const [isPolling, setIsPolling] = useState<boolean>(false);
|
||||
const [secret, setSecret] = useState<string | null>(null);
|
||||
const [
|
||||
settings,
|
||||
updateSettings,
|
||||
pluginSettings,
|
||||
setPluginSettings,
|
||||
refreshStreamyfinPluginSettings,
|
||||
] = useSettings();
|
||||
const { clearAllJellyseerData, setJellyseerrUser } = useJellyseerr();
|
||||
|
||||
useQuery({
|
||||
queryKey: ["user", api],
|
||||
@@ -105,7 +92,7 @@ export const JellyfinProvider: React.FC<{ children: ReactNode }> = ({
|
||||
return {
|
||||
authorization: `MediaBrowser Client="Streamyfin", Device=${
|
||||
Platform.OS === "android" ? "Android" : "iOS"
|
||||
}, DeviceId="${deviceId}", Version="0.25.0"`,
|
||||
}, DeviceId="${deviceId}", Version="0.23.0"`,
|
||||
};
|
||||
}, [deviceId]);
|
||||
|
||||
@@ -177,14 +164,6 @@ export const JellyfinProvider: React.FC<{ children: ReactNode }> = ({
|
||||
|
||||
useInterval(pollQuickConnect, isPolling ? 1000 : null);
|
||||
|
||||
useEffect(() => {
|
||||
(async () => {
|
||||
await refreshStreamyfinPluginSettings();
|
||||
})();
|
||||
}, []);
|
||||
|
||||
useInterval(refreshStreamyfinPluginSettings, 60 * 5 * 1000); // 5 min
|
||||
|
||||
const discoverServers = async (url: string): Promise<Server[]> => {
|
||||
const servers = await jellyfin?.discovery.getRecommendedServerCandidates(
|
||||
url
|
||||
@@ -247,39 +226,27 @@ export const JellyfinProvider: React.FC<{ children: ReactNode }> = ({
|
||||
storage.set("user", JSON.stringify(auth.data.User));
|
||||
setApi(jellyfin.createApi(api?.basePath, auth.data?.AccessToken));
|
||||
storage.set("token", auth.data?.AccessToken);
|
||||
|
||||
const recentPluginSettings = await refreshStreamyfinPluginSettings();
|
||||
if (recentPluginSettings?.jellyseerrServerUrl?.value) {
|
||||
const jellyseerrApi = new JellyseerrApi(
|
||||
recentPluginSettings.jellyseerrServerUrl.value
|
||||
);
|
||||
await jellyseerrApi.test().then((result) => {
|
||||
if (result.isValid && result.requiresPass) {
|
||||
jellyseerrApi.login(username, password).then(setJellyseerrUser);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
if (axios.isAxiosError(error)) {
|
||||
switch (error.response?.status) {
|
||||
case 401:
|
||||
throw new Error(t("login.invalid_username_or_password"));
|
||||
throw new Error("Invalid username or password");
|
||||
case 403:
|
||||
throw new Error(t("login.user_does_not_have_permission_to_log_in"));
|
||||
throw new Error("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")
|
||||
"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")
|
||||
"Server received too many requests, try again later"
|
||||
);
|
||||
case 500:
|
||||
throw new Error(t("login.there_is_a_server_error"));
|
||||
throw new Error("There is a server error");
|
||||
default:
|
||||
throw new Error(
|
||||
t("login.an_unexpected_error_occured_did_you_enter_the_correct_url")
|
||||
"An unexpected error occurred. Did you enter the server URL correctly?"
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -295,8 +262,6 @@ export const JellyfinProvider: React.FC<{ children: ReactNode }> = ({
|
||||
mutationFn: async () => {
|
||||
storage.delete("token");
|
||||
setUser(null);
|
||||
setPluginSettings(undefined);
|
||||
await clearAllJellyseerData();
|
||||
},
|
||||
onError: (error) => {
|
||||
console.error("Logout failed:", error);
|
||||
|
||||
@@ -38,6 +38,7 @@ type PlaySettingsContextType = {
|
||||
setPlayUrl: React.Dispatch<React.SetStateAction<string | null>>;
|
||||
playSessionId?: string | null;
|
||||
setOfflineSettings: (data: PlaybackType) => void;
|
||||
setMusicPlaySettings: (item: BaseItemDto, url: string) => void;
|
||||
};
|
||||
|
||||
const PlaySettingsContext = createContext<PlaySettingsContextType | undefined>(
|
||||
@@ -60,6 +61,13 @@ export const PlaySettingsProvider: React.FC<{ children: React.ReactNode }> = ({
|
||||
_setPlaySettings(data);
|
||||
}, []);
|
||||
|
||||
const setMusicPlaySettings = (item: BaseItemDto, url: string) => {
|
||||
setPlaySettings({
|
||||
item: item,
|
||||
});
|
||||
setPlayUrl(url);
|
||||
};
|
||||
|
||||
const setPlaySettings = useCallback(
|
||||
async (
|
||||
dataOrUpdater:
|
||||
@@ -139,6 +147,7 @@ export const PlaySettingsProvider: React.FC<{ children: React.ReactNode }> = ({
|
||||
setPlaySettings,
|
||||
playUrl,
|
||||
setPlayUrl,
|
||||
setMusicPlaySettings,
|
||||
setOfflineSettings,
|
||||
playSessionId,
|
||||
mediaSource,
|
||||
|
||||
Reference in New Issue
Block a user