diff --git a/app/(auth)/(tabs)/(home,libraries,search,favorites)/series/[id].tsx b/app/(auth)/(tabs)/(home,libraries,search,favorites)/series/[id].tsx
index a62405e1..9a284d33 100644
--- a/app/(auth)/(tabs)/(home,libraries,search,favorites)/series/[id].tsx
+++ b/app/(auth)/(tabs)/(home,libraries,search,favorites)/series/[id].tsx
@@ -15,7 +15,7 @@ import { Image } from "expo-image";
import { useLocalSearchParams, useNavigation } from "expo-router";
import { useAtom } from "jotai";
import React, { useEffect, useMemo } from "react";
-import { View } from "react-native";
+import { Platform, View } from "react-native";
import { useTranslation } from "react-i18next";
const page: React.FC = () => {
@@ -85,21 +85,25 @@ const page: React.FC = () => {
allEpisodes.length > 0 && (
- (
-
- )}
- DownloadedIconComponent={() => (
-
+ (
+
+ )}
+ DownloadedIconComponent={() => (
+
+ )}
/>
- )}
- />
+ >
+ )}
),
});
diff --git a/app/(auth)/player/_layout.tsx b/app/(auth)/player/_layout.tsx
index bee527e5..0eefb300 100644
--- a/app/(auth)/player/_layout.tsx
+++ b/app/(auth)/player/_layout.tsx
@@ -3,16 +3,21 @@ import React, { useEffect } from "react";
import { SystemBars } from "react-native-edge-to-edge";
import * as ScreenOrientation from "@/packages/expo-screen-orientation";
import { useSettings } from "@/utils/atoms/settings";
+import { Platform } from "react-native";
export default function Layout() {
const [settings] = useSettings();
useEffect(() => {
+ if (Platform.isTV) return;
+
if (settings.defaultVideoOrientation) {
ScreenOrientation.lockAsync(settings.defaultVideoOrientation);
}
return () => {
+ if (Platform.isTV) return;
+
if (settings.autoRotate === true) {
ScreenOrientation.unlockAsync();
} else {
diff --git a/app/_layout.tsx b/app/_layout.tsx
index 0d061be5..ad84ba0c 100644
--- a/app/_layout.tsx
+++ b/app/_layout.tsx
@@ -270,6 +270,7 @@ function Layout() {
useEffect(() => {
// If the user has auto rotate enabled, unlock the orientation
+ if (Platform.isTV) return;
if (settings.autoRotate === true) {
ScreenOrientation.unlockAsync();
} else {
diff --git a/bun.lock b/bun.lock
index 33b28594..74136017 100644
--- a/bun.lock
+++ b/bun.lock
@@ -60,7 +60,7 @@
"react-i18next": "^15.4.0",
"react-native": "npm:react-native-tvos@~0.77.0-0",
"react-native-awesome-slider": "^2.9.0",
- "react-native-bottom-tabs": "0.8.7",
+ "react-native-bottom-tabs": "0.8.6",
"react-native-circular-progress": "^1.4.1",
"react-native-compressor": "^1.10.3",
"react-native-country-flag": "^2.0.2",
@@ -1826,7 +1826,7 @@
"react-native-awesome-slider": ["react-native-awesome-slider@2.9.0", "", { "peerDependencies": { "react": "*", "react-native": "*", "react-native-gesture-handler": ">=2.0.0", "react-native-reanimated": ">=3.0.0" } }, "sha512-sc5qgX4YtM6IxjtosjgQLdsal120MvU+YWs0F2MdgQWijps22AXLDCUoBnZZ8vxVhVyJ2WnnIPrmtVBvVJjSuQ=="],
- "react-native-bottom-tabs": ["react-native-bottom-tabs@0.8.7", "", { "dependencies": { "react-freeze": "^1.0.0", "sf-symbols-typescript": "^2.0.0", "use-latest-callback": "^0.2.1" }, "peerDependencies": { "react": "*", "react-native": "*" } }, "sha512-cVQYs4r8Hb9V9oOO/SqsmBaZ7IzE/3Tpvz4mmRjNXKi1cBWC+ZpKTuqRx6EPjBCYTVK+vbAfoTM6IHS+6NVg4w=="],
+ "react-native-bottom-tabs": ["react-native-bottom-tabs@0.8.6", "", { "dependencies": { "sf-symbols-typescript": "^2.0.0", "use-latest-callback": "^0.2.1" }, "peerDependencies": { "react": "*", "react-native": "*" } }, "sha512-N5b3MoSfsEqlmvFyIyL0X0bd+QAtB+cXH1rl/+R2Kr0BefBTC7ZldGcPhgK3FhBbt0vJDpd3kLb/dvmqZd+Eag=="],
"react-native-circular-progress": ["react-native-circular-progress@1.4.1", "", { "dependencies": { "prop-types": "^15.8.1" }, "peerDependencies": { "react": ">=16.0.0", "react-native": ">=0.50.0", "react-native-svg": ">=7.0.0" } }, "sha512-HEzvI0WPuWvsCgWE3Ff2HBTMgAEQB2GvTFw0KHyD/t1STAlDDRiolu0mEGhVvihKR3jJu3v3V4qzvSklY/7XzQ=="],
diff --git a/components/DownloadItem.tsx b/components/DownloadItem.tsx
index befc34ca..e7286023 100644
--- a/components/DownloadItem.tsx
+++ b/components/DownloadItem.tsx
@@ -2,7 +2,7 @@ import { useRemuxHlsToMp4 } from "@/hooks/useRemuxHlsToMp4";
import { useDownload } from "@/providers/DownloadProvider";
import { apiAtom, userAtom } from "@/providers/JellyfinProvider";
import { queueActions, queueAtom } from "@/utils/atoms/queue";
-import {DownloadMethod, useSettings} from "@/utils/atoms/settings";
+import { DownloadMethod, useSettings } from "@/utils/atoms/settings";
import { getDefaultPlaySettings } from "@/utils/jellyfin/getDefaultPlaySettings";
import { getStreamUrl } from "@/utils/jellyfin/media/getStreamUrl";
import { saveDownloadItemInfoToDiskTmp } from "@/utils/optimize-server";
@@ -21,7 +21,7 @@ import {
import { Href, router, useFocusEffect } from "expo-router";
import { useAtom } from "jotai";
import React, { useCallback, useMemo, useRef, useState } from "react";
-import { Alert, View, ViewProps } from "react-native";
+import { Alert, Platform, View, ViewProps } from "react-native";
import { toast } from "sonner-native";
import { AudioTrackSelector } from "./AudioTrackSelector";
import { Bitrate, BitrateSelector } from "./BitrateSelector";
@@ -66,10 +66,12 @@ export const DownloadItems: React.FC = ({
const [selectedAudioStream, setSelectedAudioStream] = useState(-1);
const [selectedSubtitleStream, setSelectedSubtitleStream] =
useState(0);
- const [maxBitrate, setMaxBitrate] = useState(settings?.defaultBitrate ?? {
- key: "Max",
- value: undefined,
- });
+ const [maxBitrate, setMaxBitrate] = useState(
+ settings?.defaultBitrate ?? {
+ key: "Max",
+ value: undefined,
+ }
+ );
const userCanDownload = useMemo(
() => user?.Policy?.EnableContentDownloading,
@@ -162,7 +164,9 @@ export const DownloadItems: React.FC = ({
);
}
} else {
- toast.error(t("home.downloads.toasts.you_are_not_allowed_to_download_files"));
+ toast.error(
+ t("home.downloads.toasts.you_are_not_allowed_to_download_files")
+ );
}
}, [
queue,
@@ -333,7 +337,10 @@ export const DownloadItems: React.FC = ({
{title}
- {subtitle || t("item_card.download.download_x_item", {item_count: itemsNotDownloaded.length})}
+ {subtitle ||
+ t("item_card.download.download_x_item", {
+ item_count: itemsNotDownloaded.length,
+ })}
@@ -391,12 +398,16 @@ export const DownloadSingleItem: React.FC<{
size?: "default" | "large";
item: BaseItemDto;
}> = ({ item, size = "default" }) => {
+ if (Platform.isTV) return;
+
return (
(
diff --git a/components/ItemContent.tsx b/components/ItemContent.tsx
index 39aa1660..8fb538dd 100644
--- a/components/ItemContent.tsx
+++ b/components/ItemContent.tsx
@@ -15,6 +15,7 @@ import { SeasonEpisodesCarousel } from "@/components/series/SeasonEpisodesCarous
import useDefaultPlaySettings from "@/hooks/useDefaultPlaySettings";
import { useImageColors } from "@/hooks/useImageColors";
import { useOrientation } from "@/hooks/useOrientation";
+import * as ScreenOrientation from "@/packages/expo-screen-orientation";
import { apiAtom } from "@/providers/JellyfinProvider";
import { useSettings } from "@/utils/atoms/settings";
import { getLogoImageUrlById } from "@/utils/jellyfin/image/getLogoImageUrlById";
@@ -24,17 +25,16 @@ import {
} from "@jellyfin/sdk/lib/generated-client/models";
import { Image } from "expo-image";
import { useNavigation } from "expo-router";
-import * as ScreenOrientation from "@/packages/expo-screen-orientation";
import { useAtom } from "jotai";
import React, { useEffect, useMemo, useState } from "react";
import { Platform, View } from "react-native";
import { useSafeAreaInsets } from "react-native-safe-area-context";
-const Chromecast = !Platform.isTV ? require("./Chromecast") : null;
+import { AddToFavorites } from "./AddToFavorites";
import { ItemHeader } from "./ItemHeader";
import { ItemTechnicalDetails } from "./ItemTechnicalDetails";
import { MediaSourceSelector } from "./MediaSourceSelector";
import { MoreMoviesWithActor } from "./MoreMoviesWithActor";
-import { AddToFavorites } from "./AddToFavorites";
+const Chromecast = !Platform.isTV ? require("./Chromecast") : null;
export type SelectedOptions = {
bitrate: Bitrate;
@@ -94,7 +94,9 @@ export const ItemContent: React.FC<{ item: BaseItemDto }> = React.memo(
/>
{item.Type !== "Program" && (
-
+ {!Platform.isTV && (
+
+ )}
@@ -164,7 +166,6 @@ export const ItemContent: React.FC<{ item: BaseItemDto }> = React.memo(
}
>
- {/* {!Platform.isTV && ( */}
{item.Type !== "Program" && !Platform.isTV && (
@@ -222,13 +223,11 @@ export const ItemContent: React.FC<{ item: BaseItemDto }> = React.memo(
)}
- {/* {!Platform.isTV && ( */}
- {/* )} */}
{item.Type === "Episode" && (
diff --git a/components/PlayButton.tsx b/components/PlayButton.tsx
index 66d1c434..ff8ecab4 100644
--- a/components/PlayButton.tsx
+++ b/components/PlayButton.tsx
@@ -1,4 +1,4 @@
-import { Platform } from "react-native";
+import { Platform, Pressable } from "react-native";
import { apiAtom, userAtom } from "@/providers/JellyfinProvider";
import { itemThemeColorAtom } from "@/utils/atoms/primaryColor";
import { useSettings } from "@/utils/atoms/settings";
@@ -79,6 +79,7 @@ export const PlayButton: React.FC = ({
);
const onPress = useCallback(async () => {
+ console.log("onPress");
if (!item) return;
lightHapticFeedback();
@@ -113,105 +114,103 @@ export const PlayButton: React.FC = ({
switch (selectedIndex) {
case 0:
- if (!Platform.isTV) {
- await CastContext.getPlayServicesState().then(async (state) => {
- if (state && state !== PlayServicesState.SUCCESS) {
- CastContext.showPlayServicesErrorDialog(state);
- } else {
- // Get a new URL with the Chromecast device profile:
- try {
- const data = await getStreamUrl({
- api,
- item,
- deviceProfile: chromecastProfile,
- startTimeTicks: item?.UserData?.PlaybackPositionTicks!,
- userId: user?.Id,
- audioStreamIndex: selectedOptions.audioIndex,
- maxStreamingBitrate: selectedOptions.bitrate?.value,
- mediaSourceId: selectedOptions.mediaSource?.Id,
- subtitleStreamIndex: selectedOptions.subtitleIndex,
- });
+ await CastContext.getPlayServicesState().then(async (state) => {
+ if (state && state !== PlayServicesState.SUCCESS) {
+ CastContext.showPlayServicesErrorDialog(state);
+ } else {
+ // Get a new URL with the Chromecast device profile:
+ try {
+ const data = await getStreamUrl({
+ api,
+ item,
+ deviceProfile: chromecastProfile,
+ startTimeTicks: item?.UserData?.PlaybackPositionTicks!,
+ userId: user?.Id,
+ audioStreamIndex: selectedOptions.audioIndex,
+ maxStreamingBitrate: selectedOptions.bitrate?.value,
+ mediaSourceId: selectedOptions.mediaSource?.Id,
+ subtitleStreamIndex: selectedOptions.subtitleIndex,
+ });
- if (!data?.url) {
- console.warn("No URL returned from getStreamUrl", data);
- Alert.alert(
- t("player.client_error"),
- t("player.could_not_create_stream_for_chromecast")
- );
- return;
- }
-
- client
- .loadMedia({
- mediaInfo: {
- contentUrl: data?.url,
- contentType: "video/mp4",
- metadata:
- item.Type === "Episode"
- ? {
- type: "tvShow",
- title: item.Name || "",
- episodeNumber: item.IndexNumber || 0,
- seasonNumber: item.ParentIndexNumber || 0,
- seriesTitle: item.SeriesName || "",
- images: [
- {
- url: getParentBackdropImageUrl({
- api,
- item,
- quality: 90,
- width: 2000,
- })!,
- },
- ],
- }
- : item.Type === "Movie"
- ? {
- type: "movie",
- title: item.Name || "",
- subtitle: item.Overview || "",
- images: [
- {
- url: getPrimaryImageUrl({
- api,
- item,
- quality: 90,
- width: 2000,
- })!,
- },
- ],
- }
- : {
- type: "generic",
- title: item.Name || "",
- subtitle: item.Overview || "",
- images: [
- {
- url: getPrimaryImageUrl({
- api,
- item,
- quality: 90,
- width: 2000,
- })!,
- },
- ],
- },
- },
- startTime: 0,
- })
- .then(() => {
- // state is already set when reopening current media, so skip it here.
- if (isOpeningCurrentlyPlayingMedia) {
- return;
- }
- CastContext.showExpandedControls();
- });
- } catch (e) {
- console.log(e);
+ if (!data?.url) {
+ console.warn("No URL returned from getStreamUrl", data);
+ Alert.alert(
+ t("player.client_error"),
+ t("player.could_not_create_stream_for_chromecast")
+ );
+ return;
}
+
+ client
+ .loadMedia({
+ mediaInfo: {
+ contentUrl: data?.url,
+ contentType: "video/mp4",
+ metadata:
+ item.Type === "Episode"
+ ? {
+ type: "tvShow",
+ title: item.Name || "",
+ episodeNumber: item.IndexNumber || 0,
+ seasonNumber: item.ParentIndexNumber || 0,
+ seriesTitle: item.SeriesName || "",
+ images: [
+ {
+ url: getParentBackdropImageUrl({
+ api,
+ item,
+ quality: 90,
+ width: 2000,
+ })!,
+ },
+ ],
+ }
+ : item.Type === "Movie"
+ ? {
+ type: "movie",
+ title: item.Name || "",
+ subtitle: item.Overview || "",
+ images: [
+ {
+ url: getPrimaryImageUrl({
+ api,
+ item,
+ quality: 90,
+ width: 2000,
+ })!,
+ },
+ ],
+ }
+ : {
+ type: "generic",
+ title: item.Name || "",
+ subtitle: item.Overview || "",
+ images: [
+ {
+ url: getPrimaryImageUrl({
+ api,
+ item,
+ quality: 90,
+ width: 2000,
+ })!,
+ },
+ ],
+ },
+ },
+ startTime: 0,
+ })
+ .then(() => {
+ // state is already set when reopening current media, so skip it here.
+ if (isOpeningCurrentlyPlayingMedia) {
+ return;
+ }
+ CastContext.showExpandedControls();
+ });
+ } catch (e) {
+ console.log(e);
}
- });
- }
+ }
+ });
break;
case 1:
goToPlayer(queryString, selectedOptions.bitrate?.value);
@@ -323,75 +322,62 @@ export const PlayButton: React.FC = ({
*/
return (
-
-
-
-
-
-
+
+
-
-
-
- {runtimeTicksToMinutes(item?.RunTimeTicks)}
-
+
+
+
+
+
+
+ {runtimeTicksToMinutes(item?.RunTimeTicks)}
+
+
+
+
+ {client && (
-
+
+
- {client && (
-
-
-
-
- )}
- {!client && settings?.openInVLC && (
-
-
-
- )}
-
+ )}
+ {!client && settings?.openInVLC && (
+
+
+
+ )}
-
- {/*
-
-
- {directStream ? "Direct stream" : "Transcoded stream"}
-
- */}
-
+
+
);
};
diff --git a/components/PlayButton.tv.tsx b/components/PlayButton.tv.tsx
index 128c2184..1fb0563c 100644
--- a/components/PlayButton.tv.tsx
+++ b/components/PlayButton.tv.tsx
@@ -63,7 +63,8 @@ export const PlayButton: React.FC = ({
[router]
);
- const onPress = useCallback(async () => {
+ const onPress = () => {
+ console.log("onpress");
if (!item) return;
lightHapticFeedback();
@@ -79,15 +80,7 @@ export const PlayButton: React.FC = ({
const queryString = queryParams.toString();
goToPlayer(queryString, selectedOptions.bitrate?.value);
return;
- }, [
- item,
- settings,
- api,
- user,
- router,
- showActionSheetWithOptions,
- selectedOptions,
- ]);
+ };
const derivedTargetWidth = useDerivedValue(() => {
if (!item || !item.RunTimeTicks) return 0;
@@ -179,69 +172,55 @@ export const PlayButton: React.FC = ({
*/
return (
-
-
-
-
-
-
+
+
-
-
-
- {runtimeTicksToMinutes(item?.RunTimeTicks)}
-
+
+
+
+
+
+
+ {runtimeTicksToMinutes(item?.RunTimeTicks)}
+
+
+
+
+ {settings?.openInVLC && (
-
+
- {settings?.openInVLC && (
-
-
-
- )}
-
+ )}
-
- {/*
-
-
- {directStream ? "Direct stream" : "Transcoded stream"}
-
- */}
-
+
+
);
};
diff --git a/components/common/Text.tsx b/components/common/Text.tsx
index ef7a6491..624b9da6 100644
--- a/components/common/Text.tsx
+++ b/components/common/Text.tsx
@@ -1,19 +1,27 @@
import React from "react";
-import { TextProps } from "react-native";
+import { Platform, TextProps } from "react-native";
import { UITextView } from "react-native-uitextview";
-
+import { Text as RNText } from "react-native";
export function Text(
props: TextProps & {
uiTextView?: boolean;
}
) {
const { style, ...otherProps } = props;
-
- return (
-
- );
+ if (Platform.isTV)
+ return (
+
+ );
+ else
+ return (
+
+ );
}
diff --git a/components/downloads/ActiveDownloads.tsx b/components/downloads/ActiveDownloads.tsx
index 7b6316f8..773efab4 100644
--- a/components/downloads/ActiveDownloads.tsx
+++ b/components/downloads/ActiveDownloads.tsx
@@ -1,16 +1,15 @@
import { Text } from "@/components/common/Text";
import { useDownload } from "@/providers/DownloadProvider";
-import {DownloadMethod, useSettings} from "@/utils/atoms/settings";
+import { DownloadMethod, useSettings } from "@/utils/atoms/settings";
+import { storage } from "@/utils/mmkv";
import { JobStatus } from "@/utils/optimize-server";
import { formatTimeString } from "@/utils/time";
import { Ionicons } from "@expo/vector-icons";
-const BackGroundDownloader = !Platform.isTV
- ? require("@kesha-antonov/react-native-background-downloader")
- : null;
import { useMutation, useQueryClient } from "@tanstack/react-query";
+import { Image } from "expo-image";
import { useRouter } from "expo-router";
-const FFmpegKitProvider = !Platform.isTV ? require("ffmpeg-kit-react-native") : null;
-import { useAtom } from "jotai";
+import { t } from "i18next";
+import { useMemo } from "react";
import {
ActivityIndicator,
Platform,
@@ -21,10 +20,12 @@ import {
} from "react-native";
import { toast } from "sonner-native";
import { Button } from "../Button";
-import { Image } from "expo-image";
-import { useMemo } from "react";
-import { storage } from "@/utils/mmkv";
-import { t } from "i18next";
+const BackGroundDownloader = !Platform.isTV
+ ? require("@kesha-antonov/react-native-background-downloader")
+ : null;
+const FFmpegKitProvider = !Platform.isTV
+ ? require("ffmpeg-kit-react-native")
+ : null;
interface Props extends ViewProps {}
@@ -33,14 +34,20 @@ export const ActiveDownloads: React.FC = ({ ...props }) => {
if (processes?.length === 0)
return (
- {t("home.downloads.active_download")}
- {t("home.downloads.no_active_downloads")}
+
+ {t("home.downloads.active_download")}
+
+
+ {t("home.downloads.no_active_downloads")}
+
);
return (
- {t("home.downloads.active_downloads")}
+
+ {t("home.downloads.active_downloads")}
+
{processes?.map((p: JobStatus) => (
@@ -81,7 +88,9 @@ const DownloadCard = ({ process, ...props }: DownloadCardProps) => {
}
} else {
FFmpegKitProvider.FFmpegKit.cancel(Number(id));
- setProcesses((prev: any[]) => prev.filter((p: { id: string; }) => p.id !== id));
+ setProcesses((prev: any[]) =>
+ prev.filter((p: { id: string }) => p.id !== id)
+ );
}
},
onSuccess: () => {
@@ -156,7 +165,9 @@ const DownloadCard = ({ process, ...props }: DownloadCardProps) => {
{process.speed?.toFixed(2)}x
)}
{eta(process) && (
- {t("home.downloads.eta", {eta: eta(process)})}
+
+ {t("home.downloads.eta", { eta: eta(process) })}
+
)}
diff --git a/components/video-player/controls/Controls.tsx b/components/video-player/controls/Controls.tsx
index 3232965d..17bd2028 100644
--- a/components/video-player/controls/Controls.tsx
+++ b/components/video-player/controls/Controls.tsx
@@ -540,17 +540,19 @@ export const Controls: React.FC = ({
pointerEvents={showControls ? "auto" : "none"}
className={`flex flex-row w-full pt-2`}
>
-
-
-
-
-
+ {!Platform.isTV && (
+
+
+
+
+
+ )}
{!Platform.isTV && (
diff --git a/hooks/useRemuxHlsToMp4.ts b/hooks/useRemuxHlsToMp4.ts
index 925d9778..22ea02ce 100644
--- a/hooks/useRemuxHlsToMp4.ts
+++ b/hooks/useRemuxHlsToMp4.ts
@@ -11,7 +11,9 @@ import * as FileSystem from "expo-file-system";
import { useRouter } from "expo-router";
// import { FFmpegKit, FFmpegSession, Statistics } from "ffmpeg-kit-react-native";
-const FFMPEGKitReactNative = !Platform.isTV ? require("ffmpeg-kit-react-native") : null;
+const FFMPEGKitReactNative = !Platform.isTV
+ ? require("ffmpeg-kit-react-native")
+ : null;
import { useAtomValue } from "jotai";
import { useCallback } from "react";
import { toast } from "sonner-native";
@@ -24,8 +26,10 @@ import { Platform } from "react-native";
import { useTranslation } from "react-i18next";
type FFmpegSession = typeof FFMPEGKitReactNative.FFmpegSession;
-type Statistics = typeof FFMPEGKitReactNative.Statistics
-const FFmpegKit = FFMPEGKitReactNative.FFmpegKit;
+type Statistics = typeof FFMPEGKitReactNative.Statistics;
+const FFmpegKit = Platform.isTV
+ ? null
+ : (FFMPEGKitReactNative.FFmpegKit as typeof FFMPEGKitReactNative.FFmpegKit);
const createFFmpegCommand = (url: string, output: string) => [
"-y", // overwrite output files without asking
"-thread_queue_size 512", // https://ffmpeg.org/ffmpeg.html#toc-Advanced-options
@@ -101,7 +105,10 @@ export const useRemuxHlsToMp4 = () => {
}
setProcesses((prev: any[]) => {
- return prev.filter((process: { itemId: string | undefined; }) => process.itemId !== item.Id);
+ return prev.filter(
+ (process: { itemId: string | undefined }) =>
+ process.itemId !== item.Id
+ );
});
} catch (e) {
console.error(e);
@@ -126,7 +133,7 @@ export const useRemuxHlsToMp4 = () => {
if (!item.Id) throw new Error("Item is undefined");
setProcesses((prev: any[]) => {
- return prev.map((process: { itemId: string | undefined; }) => {
+ return prev.map((process: { itemId: string | undefined }) => {
if (process.itemId === item.Id) {
return {
...process,
@@ -161,15 +168,18 @@ export const useRemuxHlsToMp4 = () => {
// First lets save any important assets we want to present to the user offline
await onSaveAssets(api, item);
- toast.success(t("home.downloads.toasts.download_started_for", {item: item.Name}), {
- action: {
- label: "Go to download",
- onClick: () => {
- router.push("/downloads");
- toast.dismiss();
+ toast.success(
+ t("home.downloads.toasts.download_started_for", { item: item.Name }),
+ {
+ action: {
+ label: "Go to download",
+ onClick: () => {
+ router.push("/downloads");
+ toast.dismiss();
+ },
},
- },
- });
+ }
+ );
try {
const job: JobStatus = {
@@ -201,7 +211,10 @@ export const useRemuxHlsToMp4 = () => {
Error: ${error.message}, Stack: ${error.stack}`
);
setProcesses((prev: any[]) => {
- return prev.filter((process: { itemId: string | undefined; }) => process.itemId !== item.Id);
+ return prev.filter(
+ (process: { itemId: string | undefined }) =>
+ process.itemId !== item.Id
+ );
});
throw error; // Re-throw the error to propagate it to the caller
}
diff --git a/modules/vlc-player/ios/VlcPlayer.podspec b/modules/vlc-player/ios/VlcPlayer.podspec
index 97f58881..25f2d73e 100644
--- a/modules/vlc-player/ios/VlcPlayer.podspec
+++ b/modules/vlc-player/ios/VlcPlayer.podspec
@@ -5,7 +5,7 @@ Pod::Spec.new do |s|
s.description = 'A sample project description'
s.author = ''
s.homepage = 'https://docs.expo.dev/modules/'
- s.platforms = { :ios => '13.4', :tvos => '13.4' }
+ s.platforms = { :ios => '13.4', :tvos => '16' }
s.source = { git: '' }
s.static_framework = true
diff --git a/package.json b/package.json
index a04b6b4b..074e60bd 100644
--- a/package.json
+++ b/package.json
@@ -74,7 +74,7 @@
"react-i18next": "^15.4.0",
"react-native": "npm:react-native-tvos@~0.77.0-0",
"react-native-awesome-slider": "^2.9.0",
- "react-native-bottom-tabs": "0.8.7",
+ "react-native-bottom-tabs": "0.8.6",
"react-native-circular-progress": "^1.4.1",
"react-native-compressor": "^1.10.3",
"react-native-country-flag": "^2.0.2",