mirror of
https://github.com/streamyfin/streamyfin.git
synced 2026-01-15 23:59:08 +00:00
Alert and Toasts
This commit is contained in:
@@ -17,6 +17,7 @@ import {BottomSheetBackdrop, BottomSheetBackdropProps, BottomSheetModal, BottomS
|
||||
import {toast} from "sonner-native";
|
||||
import {writeToLog} from "@/utils/log";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { t } from 'i18next';
|
||||
|
||||
export default function page() {
|
||||
const navigation = useNavigation();
|
||||
@@ -68,16 +69,16 @@ export default function page() {
|
||||
}, [downloadedFiles]);
|
||||
|
||||
const deleteMovies = () => deleteFileByType("Movie")
|
||||
.then(() => toast.success("Deleted all movies successfully!"))
|
||||
.then(() => toast.success(t("home.downloads.toasts.deleted_all_movies_successfully")))
|
||||
.catch((reason) => {
|
||||
writeToLog("ERROR", reason);
|
||||
toast.error("Failed to delete all movies");
|
||||
toast.error(t("home.downloads.toasts.failed_to_delete_all_movies"));
|
||||
});
|
||||
const deleteShows = () => deleteFileByType("Episode")
|
||||
.then(() => toast.success("Deleted all TV-Series successfully!"))
|
||||
.then(() => toast.success(t("home.downloads.toasts.deleted_all_tvseries_successfully")))
|
||||
.catch((reason) => {
|
||||
writeToLog("ERROR", reason);
|
||||
toast.error("Failed to delete all TV-Series");
|
||||
toast.error(t("home.downloads.toasts.failed_to_delete_all_tvseries"));
|
||||
});
|
||||
const deleteAllMedia = async () => await Promise.all([deleteMovies(), deleteShows()])
|
||||
|
||||
@@ -216,15 +217,15 @@ function migration_20241124() {
|
||||
const router = useRouter();
|
||||
const { deleteAllFiles } = useDownload();
|
||||
Alert.alert(
|
||||
"New app version requires re-download",
|
||||
"The new update reqires content to be downloaded again. Please remove all downloaded content and try again.",
|
||||
t("home.downloads.new_app_version_requires_re_download"),
|
||||
t("home.downloads.new_app_version_requires_re_download_description"),
|
||||
[
|
||||
{
|
||||
text: "Back",
|
||||
text: t("home.downloads.back"),
|
||||
onPress: () => router.back(),
|
||||
},
|
||||
{
|
||||
text: "Delete",
|
||||
text: t("home.downloads.delete"),
|
||||
style: "destructive",
|
||||
onPress: async () => await deleteAllFiles(),
|
||||
},
|
||||
|
||||
@@ -75,7 +75,7 @@ export default function settings() {
|
||||
Haptics.notificationAsync(Haptics.NotificationFeedbackType.Success);
|
||||
} catch (e) {
|
||||
Haptics.notificationAsync(Haptics.NotificationFeedbackType.Error);
|
||||
toast.error("Error deleting files");
|
||||
toast.error(t("home.settings.toasts.error_deleting_files"));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -48,11 +48,13 @@ import {
|
||||
import { useSharedValue } from "react-native-reanimated";
|
||||
import settings from "../(tabs)/(home)/settings";
|
||||
import { useSettings } from "@/utils/atoms/settings";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
export default function page() {
|
||||
const videoRef = useRef<VlcPlayerViewRef>(null);
|
||||
const user = useAtomValue(userAtom);
|
||||
const api = useAtomValue(apiAtom);
|
||||
const { t } = useTranslation();
|
||||
|
||||
const [isPlaybackStopped, setIsPlaybackStopped] = useState(false);
|
||||
const [showControls, _setShowControls] = useState(true);
|
||||
@@ -160,7 +162,7 @@ export default function page() {
|
||||
const { mediaSource, sessionId, url } = res;
|
||||
|
||||
if (!sessionId || !mediaSource || !url) {
|
||||
Alert.alert("Error", "Failed to get stream url");
|
||||
Alert.alert(t("player.error"), t("player.failed_to_get_stream_url"));
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -466,8 +468,8 @@ export default function page() {
|
||||
onVideoError={(e) => {
|
||||
console.error("Video Error:", e.nativeEvent);
|
||||
Alert.alert(
|
||||
"Error",
|
||||
"An error occurred while playing the video. Check logs in settings."
|
||||
t("player.error"),
|
||||
t("player.an_error_occured_while_playing_the_video")
|
||||
);
|
||||
writeToLog("ERROR", "Video Error", e.nativeEvent);
|
||||
}}
|
||||
|
||||
@@ -3,10 +3,12 @@ import { useState, useCallback, useEffect, useMemo } from "react";
|
||||
import { Button, Dimensions } from "react-native";
|
||||
import { Alert, View } from "react-native";
|
||||
import YoutubePlayer, { PLAYER_STATES } from "react-native-youtube-iframe";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
export default function page() {
|
||||
const searchParams = useGlobalSearchParams();
|
||||
const navigation = useNavigation();
|
||||
const { t } = useTranslation();
|
||||
console.log(searchParams);
|
||||
|
||||
const { url } = searchParams as { url: string };
|
||||
@@ -20,7 +22,7 @@ export default function page() {
|
||||
const onStateChange = useCallback((state: PLAYER_STATES) => {
|
||||
if (state === "ended") {
|
||||
setPlaying(false);
|
||||
Alert.alert("video has finished playing!");
|
||||
Alert.alert(t("player.video_has_finished_playing"));
|
||||
}
|
||||
}, []);
|
||||
|
||||
|
||||
@@ -32,6 +32,7 @@ import { MediaSourceSelector } from "./MediaSourceSelector";
|
||||
import ProgressCircle from "./ProgressCircle";
|
||||
import { RoundButton } from "./RoundButton";
|
||||
import { SubtitleTrackSelector } from "./SubtitleTrackSelector";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
interface DownloadProps extends ViewProps {
|
||||
items: BaseItemDto[];
|
||||
@@ -55,6 +56,7 @@ export const DownloadItems: React.FC<DownloadProps> = ({
|
||||
const [user] = useAtom(userAtom);
|
||||
const [queue, setQueue] = useAtom(queueAtom);
|
||||
const [settings] = useSettings();
|
||||
const { t } = useTranslation();
|
||||
const { processes, startBackgroundDownload, downloadedFiles } = useDownload();
|
||||
const { startRemuxing } = useRemuxHlsToMp4();
|
||||
|
||||
@@ -160,7 +162,7 @@ export const DownloadItems: React.FC<DownloadProps> = ({
|
||||
);
|
||||
}
|
||||
} else {
|
||||
toast.error("You are not allowed to download files.");
|
||||
toast.error(t("home.downloads.toasts.you_are_not_allowed_to_download_files"));
|
||||
}
|
||||
}, [
|
||||
queue,
|
||||
@@ -212,8 +214,8 @@ export const DownloadItems: React.FC<DownloadProps> = ({
|
||||
|
||||
if (!res) {
|
||||
Alert.alert(
|
||||
"Something went wrong",
|
||||
"Could not get stream url from Jellyfin"
|
||||
t("home.downloads.something_went_wrong"),
|
||||
t("home.downloads.could_not_get_stream_url_from_jellyfin")
|
||||
);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -33,6 +33,7 @@ import { Button } from "./Button";
|
||||
import { SelectedOptions } from "./ItemContent";
|
||||
import { chromecastProfile } from "@/utils/profiles/chromecast";
|
||||
import * as Haptics from "expo-haptics";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
interface Props extends React.ComponentProps<typeof Button> {
|
||||
item: BaseItemDto;
|
||||
@@ -50,6 +51,7 @@ export const PlayButton: React.FC<Props> = ({
|
||||
const { showActionSheetWithOptions } = useActionSheet();
|
||||
const client = useRemoteMediaClient();
|
||||
const mediaStatus = useMediaStatus();
|
||||
const { t } = useTranslation();
|
||||
|
||||
const [colorAtom] = useAtom(itemThemeColorAtom);
|
||||
const api = useAtomValue(apiAtom);
|
||||
@@ -131,8 +133,8 @@ export const PlayButton: React.FC<Props> = ({
|
||||
if (!data?.url) {
|
||||
console.warn("No URL returned from getStreamUrl", data);
|
||||
Alert.alert(
|
||||
"Client error",
|
||||
"Could not create stream for Chromecast"
|
||||
t("player.client_error"),
|
||||
t("player.could_not_create_stream_for_chromecast")
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -22,13 +22,12 @@ import { Button } from "../Button";
|
||||
import { Image } from "expo-image";
|
||||
import { useMemo } from "react";
|
||||
import { storage } from "@/utils/mmkv";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { t } from "i18next";
|
||||
|
||||
interface Props extends ViewProps {}
|
||||
|
||||
export const ActiveDownloads: React.FC<Props> = ({ ...props }) => {
|
||||
const { processes } = useDownload();
|
||||
const { t } = useTranslation();
|
||||
if (processes?.length === 0)
|
||||
return (
|
||||
<View {...props} className="bg-neutral-900 p-4 rounded-2xl">
|
||||
@@ -84,11 +83,11 @@ const DownloadCard = ({ process, ...props }: DownloadCardProps) => {
|
||||
}
|
||||
},
|
||||
onSuccess: () => {
|
||||
toast.success("Download canceled");
|
||||
toast.success(t("home.downloads.toasts.download_cancelled"));
|
||||
},
|
||||
onError: (e) => {
|
||||
console.error(e);
|
||||
toast.error("Could not cancel download");
|
||||
toast.error(t("home.downloads.toasts.could_not_cancel_download"));
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@ import { HorizontalScroll } from "@/components/common/HorrizontalScroll";
|
||||
import { Image } from "expo-image";
|
||||
import MediaRequest from "@/utils/jellyseerr/server/entity/MediaRequest";
|
||||
import { Loader } from "../Loader";
|
||||
import { t } from "i18next";
|
||||
|
||||
const JellyseerrSeasonEpisodes: React.FC<{
|
||||
details: TvDetails;
|
||||
@@ -155,13 +156,13 @@ const JellyseerrSeasons: React.FC<{
|
||||
|
||||
const promptRequestAll = useCallback(
|
||||
() =>
|
||||
Alert.alert("Confirm", "Are you sure you want to request all seasons?", [
|
||||
Alert.alert(t("jellyseerr.confirm"), t("jellyseerr.are_you_sure_you_want_to_request_all_seasons"), [
|
||||
{
|
||||
text: "Cancel",
|
||||
text: t("jellyseerr.cancel"),
|
||||
style: "cancel",
|
||||
},
|
||||
{
|
||||
text: "Yes",
|
||||
text: t("jellyseerr.yes"),
|
||||
onPress: requestAll,
|
||||
},
|
||||
]),
|
||||
|
||||
@@ -50,7 +50,7 @@ export const JellyseerrSettings = () => {
|
||||
updateSettings({ jellyseerrServerUrl });
|
||||
},
|
||||
onError: () => {
|
||||
toast.error("Failed to login");
|
||||
toast.error(t("jellyseerr.failed_to_login"));
|
||||
},
|
||||
onSettled: () => {
|
||||
setJellyseerrPassword(undefined);
|
||||
@@ -124,16 +124,16 @@ export const JellyseerrSettings = () => {
|
||||
) : (
|
||||
<View className="flex flex-col rounded-xl overflow-hidden p-4 bg-neutral-900">
|
||||
<Text className="text-xs text-red-600 mb-2">
|
||||
{t("home.settings.jellyseer.jellyseer_warning")}
|
||||
{t("home.settings.jellyseerr.jellyseerr_warning")}
|
||||
</Text>
|
||||
<Text className="font-bold mb-1">{t("home.settings.jellyseer.server_url")}</Text>
|
||||
<Text className="font-bold mb-1">{t("home.settings.jellyseerr.server_url")}</Text>
|
||||
<View className="flex flex-col shrink mb-2">
|
||||
<Text className="text-xs text-gray-600">
|
||||
{t("home.settings.jellyseer.server_url_hint")}
|
||||
{t("home.settings.jellyseerr.server_url_hint")}
|
||||
</Text>
|
||||
</View>
|
||||
<Input
|
||||
placeholder={t("home.settings.jellyseer.server_url_placeholder")}
|
||||
placeholder={t("home.settings.jellyseerr.server_url_placeholder")}
|
||||
value={settings?.jellyseerrServerUrl ?? jellyseerrServerUrl}
|
||||
defaultValue={
|
||||
settings?.jellyseerrServerUrl ?? jellyseerrServerUrl
|
||||
@@ -163,7 +163,7 @@ export const JellyseerrSettings = () => {
|
||||
marginBottom: 8,
|
||||
}}
|
||||
>
|
||||
{promptForJellyseerrPass ? t("home.settings.jellyseer.clear_button") : t("home.settings.jellyseer.save_button")}
|
||||
{promptForJellyseerrPass ? t("home.settings.jellyseerr.clear_button") : t("home.settings.jellyseerr.save_button")}
|
||||
</Button>
|
||||
|
||||
<View
|
||||
@@ -172,11 +172,11 @@ export const JellyseerrSettings = () => {
|
||||
opacity: promptForJellyseerrPass ? 1 : 0.5,
|
||||
}}
|
||||
>
|
||||
<Text className="font-bold mb-2">{t("home.settings.jellyseer.password")}</Text>
|
||||
<Text className="font-bold mb-2">{t("home.settings.jellyseerr.password")}</Text>
|
||||
<Input
|
||||
autoFocus={true}
|
||||
focusable={true}
|
||||
placeholder={t("home.settings.jellyseer.password_placeholder", {username: user?.Name})}
|
||||
placeholder={t("home.settings.jellyseerr.password_placeholder", {username: user?.Name})}
|
||||
value={jellyseerrPassword}
|
||||
keyboardType="default"
|
||||
secureTextEntry={true}
|
||||
@@ -196,7 +196,7 @@ export const JellyseerrSettings = () => {
|
||||
className="h-12 mt-2"
|
||||
onPress={() => loginToJellyseerrMutation.mutate()}
|
||||
>
|
||||
{t("home.settings.jellyseer.login_button")}
|
||||
{t("home.settings.jellyseerr.login_button")}
|
||||
</Button>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
@@ -77,10 +77,10 @@ export const SettingToggles: React.FC<Props> = ({ ...props }) => {
|
||||
|
||||
if (settings?.autoDownload === true && !registered) {
|
||||
registerBackgroundFetchAsync();
|
||||
toast.success("Background downloads enabled");
|
||||
toast.success(t("home.settings.toasts.background_downloads_enabled"));
|
||||
} else if (settings?.autoDownload === false && registered) {
|
||||
unregisterBackgroundFetchAsync();
|
||||
toast.info("Background downloads disabled");
|
||||
toast.info(t("home.settings.toasts.background_downloads_disabled"));
|
||||
} else if (settings?.autoDownload === true && registered) {
|
||||
// Don't to anything
|
||||
} else if (settings?.autoDownload === false && !registered) {
|
||||
@@ -654,8 +654,8 @@ export const SettingToggles: React.FC<Props> = ({ ...props }) => {
|
||||
deviceId: await getOrSetDeviceId(),
|
||||
});
|
||||
if (res) {
|
||||
toast.success("Connected");
|
||||
} else toast.error("Could not connect");
|
||||
toast.success(t("home.settings.toasts.connected"));
|
||||
} else toast.error(t("home.settings.toasts.could_not_connect"));
|
||||
}}
|
||||
>
|
||||
{t("home.settings.downloads.save_button")}
|
||||
|
||||
@@ -28,6 +28,7 @@ import Issue from "@/utils/jellyseerr/server/entity/Issue";
|
||||
import { RTRating } from "@/utils/jellyseerr/server/api/rating/rottentomatoes";
|
||||
import { writeErrorLog } from "@/utils/log";
|
||||
import DiscoverSlider from "@/utils/jellyseerr/server/entity/DiscoverSlider";
|
||||
import { t } from "i18next";
|
||||
|
||||
interface SearchParams {
|
||||
query: string;
|
||||
@@ -113,7 +114,7 @@ export class JellyseerrApi {
|
||||
if (inRange(status, 200, 299)) {
|
||||
if (data.version < "2.0.0") {
|
||||
const error =
|
||||
"Jellyseerr server does not meet minimum version requirements! Please update to at least 2.0.0";
|
||||
t("jellyseerr.toasts.jellyseer_does_not_meet_requirements");
|
||||
toast.error(error);
|
||||
throw Error(error);
|
||||
}
|
||||
@@ -127,7 +128,7 @@ export class JellyseerrApi {
|
||||
requiresPass: true,
|
||||
};
|
||||
}
|
||||
toast.error(`Jellyseerr test failed. Please try again.`);
|
||||
toast.error(t("jellyseerr.toasts.jellyseerr_test_failed"));
|
||||
writeErrorLog(
|
||||
`Jellyseerr returned a ${status} for url:\n` +
|
||||
response.config.url +
|
||||
@@ -140,7 +141,7 @@ export class JellyseerrApi {
|
||||
};
|
||||
})
|
||||
.catch((e) => {
|
||||
const msg = "Failed to test jellyseerr server url";
|
||||
const msg = t("jellyseerr.toasts.failed_to_test_jellyseerr_server_url");
|
||||
toast.error(msg);
|
||||
console.error(msg, e);
|
||||
return {
|
||||
@@ -259,7 +260,7 @@ export class JellyseerrApi {
|
||||
const issue = response.data;
|
||||
|
||||
if (issue.status === IssueStatus.OPEN) {
|
||||
toast.success("Issue submitted!");
|
||||
toast.success(t("jellyseerr.toasts.issue_submitted"));
|
||||
}
|
||||
return issue;
|
||||
});
|
||||
@@ -342,13 +343,13 @@ export const useJellyseerr = () => {
|
||||
switch (mediaRequest.status) {
|
||||
case MediaRequestStatus.PENDING:
|
||||
case MediaRequestStatus.APPROVED:
|
||||
toast.success(`Requested ${title}!`);
|
||||
toast.success(t("jellyseerr.toasts.requested_item", {item: title}));
|
||||
break;
|
||||
case MediaRequestStatus.DECLINED:
|
||||
toast.error(`You don't have permission to request!`);
|
||||
toast.error(t("jellyseerr.toasts.you_dont_have_permission_to_request"));
|
||||
break;
|
||||
case MediaRequestStatus.FAILED:
|
||||
toast.error(`Something went wrong requesting media!`);
|
||||
toast.error(t("jellyseerr.toasts.something_went_wrong_requesting_media"));
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
@@ -18,6 +18,7 @@ import useDownloadHelper from "@/utils/download";
|
||||
import { Api } from "@jellyfin/sdk";
|
||||
import { useSettings } from "@/utils/atoms/settings";
|
||||
import { JobStatus } from "@/utils/optimize-server";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
const createFFmpegCommand = (url: string, output: string) => [
|
||||
"-y", // overwrite output files without asking
|
||||
@@ -49,6 +50,7 @@ export const useRemuxHlsToMp4 = () => {
|
||||
const api = useAtomValue(apiAtom);
|
||||
const router = useRouter();
|
||||
const queryClient = useQueryClient();
|
||||
const { t } = useTranslation();
|
||||
|
||||
const [settings] = useSettings();
|
||||
const { saveImage } = useImageStorage();
|
||||
@@ -84,7 +86,7 @@ export const useRemuxHlsToMp4 = () => {
|
||||
queryKey: ["downloadedItems"],
|
||||
});
|
||||
saveDownloadedItemInfo(item, stat.getSize());
|
||||
toast.success("Download completed");
|
||||
toast.success(t("home.downloads.toasts.download_completed"));
|
||||
}
|
||||
|
||||
setProcesses((prev) => {
|
||||
@@ -144,7 +146,7 @@ export const useRemuxHlsToMp4 = () => {
|
||||
// First lets save any important assets we want to present to the user offline
|
||||
await onSaveAssets(api, item);
|
||||
|
||||
toast.success(`Download started for ${item.Name}`, {
|
||||
toast.success(t("home.downloads.toasts.download_started_for", {item: item.Name}), {
|
||||
action: {
|
||||
label: "Go to download",
|
||||
onClick: () => {
|
||||
|
||||
@@ -2,6 +2,7 @@ import { useEffect } from "react";
|
||||
import { Alert } from "react-native";
|
||||
import { useRouter } from "expo-router";
|
||||
import { useWebSocketContext } from "@/providers/WebSocketProvider";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
interface UseWebSocketProps {
|
||||
isPlaying: boolean;
|
||||
@@ -18,6 +19,7 @@ export const useWebSocket = ({
|
||||
}: UseWebSocketProps) => {
|
||||
const router = useRouter();
|
||||
const { ws } = useWebSocketContext();
|
||||
const { t } = useTranslation();
|
||||
|
||||
useEffect(() => {
|
||||
if (!ws) return;
|
||||
@@ -40,7 +42,7 @@ export const useWebSocket = ({
|
||||
console.log("Command ~ DisplayMessage");
|
||||
const title = json?.Data?.Arguments?.Header;
|
||||
const body = json?.Data?.Arguments?.Text;
|
||||
Alert.alert("Message from server: " + title, body);
|
||||
Alert.alert(t("player.message_from_server", {message: title}), body);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -50,6 +50,7 @@ import useDownloadHelper from "@/utils/download";
|
||||
import { FileInfo } from "expo-file-system";
|
||||
import * as Haptics from "expo-haptics";
|
||||
import * as Application from "expo-application";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
export type DownloadedItem = {
|
||||
item: Partial<BaseItemDto>;
|
||||
@@ -68,6 +69,7 @@ const DownloadContext = createContext<ReturnType<
|
||||
|
||||
function useDownloadProvider() {
|
||||
const queryClient = useQueryClient();
|
||||
const { t } = useTranslation();
|
||||
const [settings] = useSettings();
|
||||
const router = useRouter();
|
||||
const [api] = useAtom(apiAtom);
|
||||
@@ -137,9 +139,9 @@ function useDownloadProvider() {
|
||||
if (settings.autoDownload) {
|
||||
startDownload(job);
|
||||
} else {
|
||||
toast.info(`${job.item.Name} is ready to be downloaded`, {
|
||||
toast.info(t("home.downloads.toasts.item_is_ready_to_be_downloaded",{item: job.item.Name}), {
|
||||
action: {
|
||||
label: "Go to downloads",
|
||||
label: t("home.downloads.toasts.go_to_downloads"),
|
||||
onClick: () => {
|
||||
router.push("/downloads");
|
||||
toast.dismiss();
|
||||
@@ -222,9 +224,9 @@ function useDownloadProvider() {
|
||||
},
|
||||
});
|
||||
|
||||
toast.info(`Download started for ${process.item.Name}`, {
|
||||
toast.info(t("home.downloads.toasts.download_stated_for_item", {item: process.item.Name}), {
|
||||
action: {
|
||||
label: "Go to downloads",
|
||||
label: t("home.downloads.toasts.go_to_downloads"),
|
||||
onClick: () => {
|
||||
router.push("/downloads");
|
||||
toast.dismiss();
|
||||
@@ -273,10 +275,10 @@ function useDownloadProvider() {
|
||||
process.item,
|
||||
doneHandler.bytesDownloaded
|
||||
);
|
||||
toast.success(`Download completed for ${process.item.Name}`, {
|
||||
toast.success(t("home.downloads.toasts.download_completed_for_item", {item: process.item.Name}), {
|
||||
duration: 3000,
|
||||
action: {
|
||||
label: "Go to downloads",
|
||||
label: t("home.downloads.toasts.go_to_downloads"),
|
||||
onClick: () => {
|
||||
router.push("/downloads");
|
||||
toast.dismiss();
|
||||
@@ -298,7 +300,7 @@ function useDownloadProvider() {
|
||||
if (error.errorCode === 404) {
|
||||
errorMsg = "File not found on server";
|
||||
}
|
||||
toast.error(`Download failed for ${process.item.Name} - ${errorMsg}`);
|
||||
toast.error(t("home.downloads.toasts.download_failed_for_item", {item: process.item.Name, error: errorMsg}));
|
||||
writeToLog("ERROR", `Download failed for ${process.item.Name}`, {
|
||||
error,
|
||||
processDetails: {
|
||||
@@ -355,9 +357,9 @@ function useDownloadProvider() {
|
||||
throw new Error("Failed to start optimization job");
|
||||
}
|
||||
|
||||
toast.success(`Queued ${item.Name} for optimization`, {
|
||||
toast.success(t("home.downloads.toasts.queued_item_for_optimization", {item: item.Name}), {
|
||||
action: {
|
||||
label: "Go to download",
|
||||
label: t("home.downloads.toasts.go_to_downloads"),
|
||||
onClick: () => {
|
||||
router.push("/downloads");
|
||||
toast.dismiss();
|
||||
@@ -375,21 +377,21 @@ function useDownloadProvider() {
|
||||
headers: error.response?.headers,
|
||||
});
|
||||
toast.error(
|
||||
`Failed to start download for ${item.Name}: ${error.message}`
|
||||
t("home.downloads.toasts.failed_to_start_download_for_item", {item: item.Name, message: error.message})
|
||||
);
|
||||
if (error.response) {
|
||||
toast.error(
|
||||
`Server responded with status ${error.response.status}`
|
||||
t("home.downloads.toasts.server_responded_with_status", {statusCode: error.response.status})
|
||||
);
|
||||
} else if (error.request) {
|
||||
toast.error("No response received from server");
|
||||
t("home.downloads.toasts.no_response_received_from_server");
|
||||
} else {
|
||||
toast.error("Error setting up the request");
|
||||
}
|
||||
} else {
|
||||
console.error("Non-Axios error:", error);
|
||||
toast.error(
|
||||
`Failed to start download for ${item.Name}: Unexpected error`
|
||||
t("home.downloads.toasts.failed_to_start_download_for_item_unexpected_error", {item: item.Name})
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -405,11 +407,11 @@ function useDownloadProvider() {
|
||||
queryClient.invalidateQueries({ queryKey: ["downloadedItems"] }),
|
||||
])
|
||||
.then(() =>
|
||||
toast.success("All files, folders, and jobs deleted successfully")
|
||||
toast.success(t("home.downloads.toasts.all_files_folders_jobs_deleted"))
|
||||
)
|
||||
.catch((reason) => {
|
||||
console.error("Failed to delete all files, folders, and jobs:", reason);
|
||||
toast.error("An error occurred while deleting files and jobs");
|
||||
toast.error(t("home.downloads.toasts.an_error_occured_while_deleting_files_and_jobs"));
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
@@ -107,8 +107,8 @@
|
||||
"optimized_versions_server_hint": "Set the URL for the optimized versions server for downloads.",
|
||||
"save_button": "Save"
|
||||
},
|
||||
"jellyseer": {
|
||||
"jellyseer_warning": "This integration is in its early stages. Expect things to change.",
|
||||
"jellyseerr": {
|
||||
"jellyseerr_warning": "This integration is in its early stages. Expect things to change.",
|
||||
"server_url": "Server URL",
|
||||
"server_url_hint": "Example: http(s)://your-host.url\n(add port if required)",
|
||||
"server_url_placeholder": "Jellyseerr URL...",
|
||||
@@ -134,6 +134,13 @@
|
||||
"app_language": "App language",
|
||||
"app_language_description": "Select the language for the app.",
|
||||
"system": "System"
|
||||
},
|
||||
"toasts":{
|
||||
"error_deleting_files": "Error deleting files",
|
||||
"background_downloads_enabled": "Background downloads enabled",
|
||||
"background_downloads_disabled": "Background downloads disabled",
|
||||
"connected": "Connected",
|
||||
"could_not_connect": "Could not connect"
|
||||
}
|
||||
},
|
||||
"downloads": {
|
||||
@@ -150,7 +157,36 @@
|
||||
"active_download": "Active download",
|
||||
"no_active_downloads": "No active downloads",
|
||||
"active_downloads": "Active downloads",
|
||||
"toasts": {}
|
||||
"new_app_version_requires_re_download": "New app version requires re-download",
|
||||
"new_app_version_requires_re_download_description": "The new update reqires content to be downloaded again. Please remove all downloaded content and try again.",
|
||||
"back": "Back",
|
||||
"delete": "Delete",
|
||||
"something_went_wrong": "Something went wrong",
|
||||
"could_not_get_stream_url_from_jellyfin": "Could not get stream URL from Jellyfin",
|
||||
"toasts": {
|
||||
"you_are_not_allowed_to_download_files": "You are not allowed to download files.",
|
||||
"deleted_all_movies_successfully": "Deleted all movies successfully!",
|
||||
"failed_to_delete_all_movies": "Failed to delete all movies",
|
||||
"deleted_all_tvseries_successfully": "Deleted all TV-Series successfully!",
|
||||
"failed_to_delete_all_tvseries": "Failed to delete all TV-Series",
|
||||
"download_cancelled": "Download cancelled",
|
||||
"could_not_cancel_download": "Could not cancel download",
|
||||
"download_completed": "Download completed",
|
||||
"download_started_for": "Download started for {{item}}",
|
||||
"item_is_ready_to_be_downloaded": "{{item}} is ready to be downloaded",
|
||||
"download_stated_for_item": "Download started for {{item}}",
|
||||
"download_failed_for_item": "Download failed for {{item}} - {{error}}",
|
||||
"download_completed_for_item": "Download completed for {{item}}",
|
||||
"queued_item_for_optimization": "Queued {{item}} for optimization",
|
||||
"failed_to_start_download_for_item": "Failed to start download for {{item}}: {{message}}",
|
||||
"server_responded_with_status_code": "Server responded with status {{statusCode}}",
|
||||
"no_response_received_from_server": "No response received from server",
|
||||
"error_setting_up_the_request": "Error setting up the request",
|
||||
"failed_to_start_download_for_item_unexpected_error": "Failed to start download for {{item}}: Unexpected error",
|
||||
"all_files_folders_and_jobs_deleted_successfully": "All files, folders and jobs deleted successfully",
|
||||
"an_error_occured_while_deleting_files_and_jobs": "An error occurred while deleting files and jobs",
|
||||
"go_to_downloads": "Go to downloads"
|
||||
}
|
||||
}
|
||||
},
|
||||
"search": {
|
||||
@@ -164,6 +200,31 @@
|
||||
"no_results": "No results",
|
||||
"no_libraries_found": "No libraries found"
|
||||
},
|
||||
"player": {
|
||||
"error": "Error",
|
||||
"failed_to_get_stream_url": "Failed to get stream URL",
|
||||
"an_error_occured_while_playing_the_video": "An error occurred while playing the video. Check logs in settings.",
|
||||
"client_error": "Client error",
|
||||
"could_not_create_stream_for_chromecast": "Could not create stream for Chromecast",
|
||||
"message_from_server": "Message from server: {{message}}",
|
||||
"video_has_finished_playing": "Video has finished playing!"
|
||||
},
|
||||
"jellyseerr":{
|
||||
"confirm": "Confirm",
|
||||
"cancel": "Cancel",
|
||||
"yes": "Yes",
|
||||
"are_you_sure_you_want_to_request_all_seasons": "Are you sure you want to request all seasons?",
|
||||
"failed_to_login": "Failed to login",
|
||||
"toasts": {
|
||||
"jellyseer_does_not_meet_requirements": "Jellyseerr server does not meet minimum version requirements! Please update to at least 2.0.0",
|
||||
"jellyseerr_test_failed": "Jellyseerr test failed. Please try again.",
|
||||
"failed_to_test_jellyseerr_server_url": "Failed to test jellyseerr server url",
|
||||
"issue_submitted": "Issue submitted!",
|
||||
"requested_item": "Requested {{item}}!",
|
||||
"you_dont_have_permission_to_request": "You don't have permission to request!",
|
||||
"something_went_wrong_requesting_media": "Something went wrong requesting media!"
|
||||
}
|
||||
},
|
||||
"tabs": {
|
||||
"home": "Home",
|
||||
"search": "Search",
|
||||
|
||||
Reference in New Issue
Block a user