fix more import for tv

This commit is contained in:
sarendsen
2025-02-07 14:22:54 +01:00
parent 9f41861dcf
commit 33adea2819
20 changed files with 156 additions and 119 deletions

View File

@@ -26,14 +26,18 @@ export default function IndexLayout() {
headerShadowVisible: false, headerShadowVisible: false,
headerRight: () => ( headerRight: () => (
<View className="flex flex-row items-center space-x-2"> <View className="flex flex-row items-center space-x-2">
{!Platform.isTV && <Chromecast />} {!Platform.isTV && (
<TouchableOpacity <>
onPress={() => { <Chromecast />
router.push("/(auth)/settings"); <TouchableOpacity
}} onPress={() => {
> router.push("/(auth)/settings");
<Feather name="settings" color={"white"} size={22} /> }}
</TouchableOpacity> >
<Feather name="settings" color={"white"} size={22} />
</TouchableOpacity>
</>
)}
</View> </View>
), ),
}} }}

View File

@@ -5,7 +5,7 @@ import { Feather, Ionicons } from "@expo/vector-icons";
import { Image } from "expo-image"; import { Image } from "expo-image";
import { useFocusEffect, useRouter } from "expo-router"; import { useFocusEffect, useRouter } from "expo-router";
import { useCallback } from "react"; import { useCallback } from "react";
import {useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { Linking, TouchableOpacity, View } from "react-native"; import { Linking, TouchableOpacity, View } from "react-native";
export default function page() { export default function page() {
@@ -30,10 +30,10 @@ export default function page() {
</View> </View>
<View> <View>
<Text className="text-lg font-bold">{t("home.intro.features_title")}</Text> <Text className="text-lg font-bold">
<Text className="text-xs"> {t("home.intro.features_title")}
{t("home.intro.features_description")}
</Text> </Text>
<Text className="text-xs">{t("home.intro.features_description")}</Text>
<View className="flex flex-row items-center mt-4"> <View className="flex flex-row items-center mt-4">
<Image <Image
source={require("@/assets/icons/jellyseerr-logo.svg")} source={require("@/assets/icons/jellyseerr-logo.svg")}
@@ -60,7 +60,9 @@ export default function page() {
<Ionicons name="cloud-download-outline" size={32} color="white" /> <Ionicons name="cloud-download-outline" size={32} color="white" />
</View> </View>
<View className="shrink ml-2"> <View className="shrink ml-2">
<Text className="font-bold mb-1">{t("home.intro.downloads_feature_title")}</Text> <Text className="font-bold mb-1">
{t("home.intro.downloads_feature_title")}
</Text>
<Text className="shrink text-xs"> <Text className="shrink text-xs">
{t("home.intro.downloads_feature_description")} {t("home.intro.downloads_feature_description")}
</Text> </Text>
@@ -94,7 +96,9 @@ export default function page() {
<Feather name="settings" size={28} color={"white"} /> <Feather name="settings" size={28} color={"white"} />
</View> </View>
<View className="shrink ml-2"> <View className="shrink ml-2">
<Text className="font-bold mb-1">{t("home.intro.centralised_settings_plugin_title")}</Text> <Text className="font-bold mb-1">
{t("home.intro.centralised_settings_plugin_title")}
</Text>
<Text className="shrink text-xs"> <Text className="shrink text-xs">
{t("home.intro.centralised_settings_plugin_description")}{" "} {t("home.intro.centralised_settings_plugin_description")}{" "}
<Text <Text
@@ -127,7 +131,9 @@ export default function page() {
}} }}
className="mt-4" className="mt-4"
> >
<Text className="text-purple-600 text-center">{t("home.intro.go_to_settings_button")}</Text> <Text className="text-purple-600 text-center">
{t("home.intro.go_to_settings_button")}
</Text>
</TouchableOpacity> </TouchableOpacity>
</View> </View>
</View> </View>

View File

@@ -36,9 +36,9 @@ import React, {
useRef, useRef,
useState, useState,
} from "react"; } from "react";
import { TouchableOpacity, View } from "react-native"; import { Platform, TouchableOpacity, View } from "react-native";
import { useSafeAreaInsets } from "react-native-safe-area-context"; import { useSafeAreaInsets } from "react-native-safe-area-context";
import * as DropdownMenu from "zeego/dropdown-menu"; const DropdownMenu = !Platform.isTV ? require("zeego/dropdown-menu") : null;
import RequestModal from "@/components/jellyseerr/RequestModal"; import RequestModal from "@/components/jellyseerr/RequestModal";
import { ANIME_KEYWORD_ID } from "@/utils/jellyseerr/server/api/themoviedb/constants"; import { ANIME_KEYWORD_ID } from "@/utils/jellyseerr/server/api/themoviedb/constants";
import { MediaRequestBody } from "@/utils/jellyseerr/server/interfaces/api/requestInterfaces"; import { MediaRequestBody } from "@/utils/jellyseerr/server/interfaces/api/requestInterfaces";

BIN
bun.lockb

Binary file not shown.

View File

@@ -1,7 +1,7 @@
import { MediaSourceInfo } from "@jellyfin/sdk/lib/generated-client/models"; import { MediaSourceInfo } from "@jellyfin/sdk/lib/generated-client/models";
import { useMemo } from "react"; import { useMemo } from "react";
import { TouchableOpacity, View } from "react-native"; import { Platform, TouchableOpacity, View } from "react-native";
import * as DropdownMenu from "zeego/dropdown-menu"; const DropdownMenu = !Platform.isTV ? require("zeego/dropdown-menu") : null;
import { Text } from "./common/Text"; import { Text } from "./common/Text";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
@@ -17,6 +17,7 @@ export const AudioTrackSelector: React.FC<Props> = ({
selected, selected,
...props ...props
}) => { }) => {
if (Platform.isTV) return null;
const audioStreams = useMemo( const audioStreams = useMemo(
() => source?.MediaStreams?.filter((x) => x.Type === "Audio"), () => source?.MediaStreams?.filter((x) => x.Type === "Audio"),
[source] [source]

View File

@@ -1,5 +1,5 @@
import { TouchableOpacity, View } from "react-native"; import { Platform, TouchableOpacity, View } from "react-native";
import * as DropdownMenu from "zeego/dropdown-menu"; const DropdownMenu = !Platform.isTV ? require("zeego/dropdown-menu") : null;
import { Text } from "./common/Text"; import { Text } from "./common/Text";
import { useMemo } from "react"; import { useMemo } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
@@ -54,6 +54,7 @@ export const BitrateSelector: React.FC<Props> = ({
inverted, inverted,
...props ...props
}) => { }) => {
if (Platform.isTV) return null;
const sorted = useMemo(() => { const sorted = useMemo(() => {
if (inverted) if (inverted)
return BITRATES.sort( return BITRATES.sort(

View File

@@ -3,8 +3,8 @@ import {
MediaSourceInfo, MediaSourceInfo,
} from "@jellyfin/sdk/lib/generated-client/models"; } from "@jellyfin/sdk/lib/generated-client/models";
import { useMemo } from "react"; import { useMemo } from "react";
import { TouchableOpacity, View } from "react-native"; import { Platform, TouchableOpacity, View } from "react-native";
import * as DropdownMenu from "zeego/dropdown-menu"; const DropdownMenu = !Platform.isTV ? require("zeego/dropdown-menu") : null;
import { Text } from "./common/Text"; import { Text } from "./common/Text";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
@@ -20,6 +20,7 @@ export const MediaSourceSelector: React.FC<Props> = ({
selected, selected,
...props ...props
}) => { }) => {
if (Platform.isTV) return null;
const selectedName = useMemo( const selectedName = useMemo(
() => () =>
item.MediaSources?.find((x) => x.Id === selected?.Id)?.MediaStreams?.find( item.MediaSources?.find((x) => x.Id === selected?.Id)?.MediaStreams?.find(

View File

@@ -2,7 +2,7 @@ import { tc } from "@/utils/textTools";
import { MediaSourceInfo } from "@jellyfin/sdk/lib/generated-client/models"; import { MediaSourceInfo } from "@jellyfin/sdk/lib/generated-client/models";
import { useMemo } from "react"; import { useMemo } from "react";
import { Platform, TouchableOpacity, View } from "react-native"; import { Platform, TouchableOpacity, View } from "react-native";
import * as DropdownMenu from "zeego/dropdown-menu"; const DropdownMenu = !Platform.isTV ? require("zeego/dropdown-menu") : null;
import { Text } from "./common/Text"; import { Text } from "./common/Text";
import { SubtitleHelper } from "@/utils/SubtitleHelper"; import { SubtitleHelper } from "@/utils/SubtitleHelper";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
@@ -21,6 +21,7 @@ export const SubtitleTrackSelector: React.FC<Props> = ({
isTranscoding, isTranscoding,
...props ...props
}) => { }) => {
if (Platform.isTV) return null;
const subtitleStreams = useMemo(() => { const subtitleStreams = useMemo(() => {
const subtitleHelper = new SubtitleHelper(source?.MediaStreams ?? []); const subtitleHelper = new SubtitleHelper(source?.MediaStreams ?? []);

View File

@@ -1,22 +1,27 @@
import * as DropdownMenu from "zeego/dropdown-menu"; const DropdownMenu = !Platform.isTV ? require("zeego/dropdown-menu") : null;
import {TouchableOpacity, View, ViewProps} from "react-native"; import { Platform, TouchableOpacity, View, ViewProps } from "react-native";
import {Text} from "@/components/common/Text"; import { Text } from "@/components/common/Text";
import React, {PropsWithChildren, ReactNode, useEffect, useState} from "react"; import React, {
PropsWithChildren,
ReactNode,
useEffect,
useState,
} from "react";
import DisabledSetting from "@/components/settings/DisabledSetting"; import DisabledSetting from "@/components/settings/DisabledSetting";
interface Props<T> { interface Props<T> {
data: T[] data: T[];
disabled?: boolean disabled?: boolean;
placeholderText?: string, placeholderText?: string;
keyExtractor: (item: T) => string keyExtractor: (item: T) => string;
titleExtractor: (item: T) => string | undefined titleExtractor: (item: T) => string | undefined;
title: string | ReactNode, title: string | ReactNode;
label: string, label: string;
onSelected: (...item: T[]) => void onSelected: (...item: T[]) => void;
multi?: boolean multi?: boolean;
} }
const Dropdown = <T extends unknown>({ const Dropdown = <T extends unknown>({
data, data,
disabled, disabled,
placeholderText, placeholderText,
@@ -28,38 +33,32 @@ const Dropdown = <T extends unknown>({
multi = false, multi = false,
...props ...props
}: PropsWithChildren<Props<T> & ViewProps>) => { }: PropsWithChildren<Props<T> & ViewProps>) => {
if (Platform.isTV) return null;
const [selected, setSelected] = useState<T[]>(); const [selected, setSelected] = useState<T[]>();
useEffect(() => { useEffect(() => {
if (selected !== undefined) { if (selected !== undefined) {
onSelected(...selected) onSelected(...selected);
} }
}, [selected]); }, [selected]);
return ( return (
<DisabledSetting <DisabledSetting disabled={disabled === true} showText={false} {...props}>
disabled={disabled === true}
showText={false}
{...props}
>
<DropdownMenu.Root> <DropdownMenu.Root>
<DropdownMenu.Trigger> <DropdownMenu.Trigger>
{typeof title === 'string' ? ( {typeof title === "string" ? (
<View className="flex flex-col"> <View className="flex flex-col">
<Text className="opacity-50 mb-1 text-xs"> <Text className="opacity-50 mb-1 text-xs">{title}</Text>
{title} <TouchableOpacity className="bg-neutral-900 h-10 rounded-xl border-neutral-800 border px-3 py-2 flex flex-row items-center justify-between">
</Text>
<TouchableOpacity
className="bg-neutral-900 h-10 rounded-xl border-neutral-800 border px-3 py-2 flex flex-row items-center justify-between">
<Text style={{}} className="" numberOfLines={1}> <Text style={{}} className="" numberOfLines={1}>
{selected?.length !== undefined ? selected.map(titleExtractor).join(",") : placeholderText} {selected?.length !== undefined
? selected.map(titleExtractor).join(",")
: placeholderText}
</Text> </Text>
</TouchableOpacity> </TouchableOpacity>
</View> </View>
) : ( ) : (
<> <>{title}</>
{title}
</>
)} )}
</DropdownMenu.Trigger> </DropdownMenu.Trigger>
<DropdownMenu.Content <DropdownMenu.Content
@@ -72,37 +71,48 @@ const Dropdown = <T extends unknown>({
sideOffset={0} sideOffset={0}
> >
<DropdownMenu.Label>{label}</DropdownMenu.Label> <DropdownMenu.Label>{label}</DropdownMenu.Label>
{data.map((item, idx) => ( {data.map((item, idx) =>
multi ? ( multi ? (
<DropdownMenu.CheckboxItem <DropdownMenu.CheckboxItem
value={selected?.some(s => keyExtractor(s) == keyExtractor(item)) ? 'on' : 'off'} value={
key={keyExtractor(item)} selected?.some((s) => keyExtractor(s) == keyExtractor(item))
onValueChange={(next, previous) => ? "on"
setSelected((p) => { : "off"
const prev = p || [] }
if (next == 'on') { key={keyExtractor(item)}
return [...prev, item] onValueChange={(next, previous) =>
} setSelected((p) => {
return [...prev.filter(p => keyExtractor(p) !== keyExtractor(item))] const prev = p || [];
}) if (next == "on") {
} return [...prev, item];
> }
<DropdownMenu.ItemTitle>{titleExtractor(item)}</DropdownMenu.ItemTitle> return [
</DropdownMenu.CheckboxItem> ...prev.filter(
) (p) => keyExtractor(p) !== keyExtractor(item)
: ( ),
<DropdownMenu.Item ];
key={keyExtractor(item)} })
onSelect={() => setSelected([item])} }
> >
<DropdownMenu.ItemTitle>{titleExtractor(item)}</DropdownMenu.ItemTitle> <DropdownMenu.ItemTitle>
</DropdownMenu.Item> {titleExtractor(item)}
) </DropdownMenu.ItemTitle>
))} </DropdownMenu.CheckboxItem>
) : (
<DropdownMenu.Item
key={keyExtractor(item)}
onSelect={() => setSelected([item])}
>
<DropdownMenu.ItemTitle>
{titleExtractor(item)}
</DropdownMenu.ItemTitle>
</DropdownMenu.Item>
)
)}
</DropdownMenu.Content> </DropdownMenu.Content>
</DropdownMenu.Root> </DropdownMenu.Root>
</DisabledSetting> </DisabledSetting>
) );
}; };
export default Dropdown; export default Dropdown;

View File

@@ -7,7 +7,7 @@ import { useRouter, useSegments } from "expo-router";
import { PropsWithChildren, useCallback } from "react"; import { PropsWithChildren, useCallback } from "react";
import { TouchableOpacity, TouchableOpacityProps } from "react-native"; import { TouchableOpacity, TouchableOpacityProps } from "react-native";
import { useActionSheet } from "@expo/react-native-action-sheet"; import { useActionSheet } from "@expo/react-native-action-sheet";
import * as Haptics from "expo-haptics"; import { useHaptic } from "@/hooks/useHaptic";
interface Props extends TouchableOpacityProps { interface Props extends TouchableOpacityProps {
item: BaseItemDto; item: BaseItemDto;
@@ -74,10 +74,10 @@ export const TouchableItemRouter: React.FC<PropsWithChildren<Props>> = ({
async (selectedIndex) => { async (selectedIndex) => {
if (selectedIndex === 0) { if (selectedIndex === 0) {
await markAsPlayedStatus(true); await markAsPlayedStatus(true);
Haptics.notificationAsync(Haptics.NotificationFeedbackType.Success); // Haptics.notificationAsync(Haptics.NotificationFeedbackType.Success);
} else if (selectedIndex === 1) { } else if (selectedIndex === 1) {
await markAsPlayedStatus(false); await markAsPlayedStatus(false);
Haptics.notificationAsync(Haptics.NotificationFeedbackType.Success); // Haptics.notificationAsync(Haptics.NotificationFeedbackType.Success);
} }
} }
); );

View File

@@ -1,7 +1,7 @@
import { BaseItemDto } from "@jellyfin/sdk/lib/generated-client/models"; import { BaseItemDto } from "@jellyfin/sdk/lib/generated-client/models";
import { useEffect, useMemo } from "react"; import { useEffect, useMemo } from "react";
import { TouchableOpacity, View } from "react-native"; import { Platform, TouchableOpacity, View } from "react-native";
import * as DropdownMenu from "zeego/dropdown-menu"; const DropdownMenu = !Platform.isTV ? require("zeego/dropdown-menu") : null;
import { Text } from "../common/Text"; import { Text } from "../common/Text";
import { t } from "i18next"; import { t } from "i18next";
@@ -30,6 +30,8 @@ export const SeasonDropdown: React.FC<Props> = ({
state, state,
onSelect, onSelect,
}) => { }) => {
if (Platform.isTV) return null;
const keys = useMemo<SeasonKeys>( const keys = useMemo<SeasonKeys>(
() => () =>
item.Type === "Episode" item.Type === "Episode"

View File

@@ -1,4 +1,4 @@
import * as DropdownMenu from "zeego/dropdown-menu"; const DropdownMenu = !Platform.isTV ? require("zeego/dropdown-menu") : null;
import { Platform, TouchableOpacity, View, ViewProps } from "react-native"; import { Platform, TouchableOpacity, View, ViewProps } from "react-native";
import { Text } from "../common/Text"; import { Text } from "../common/Text";
import { useSettings } from "@/utils/atoms/settings"; import { useSettings } from "@/utils/atoms/settings";
@@ -10,14 +10,12 @@ import { APP_LANGUAGES } from "@/i18n";
interface Props extends ViewProps {} interface Props extends ViewProps {}
export const AppLanguageSelector: React.FC<Props> = ({ ...props }) => { export const AppLanguageSelector: React.FC<Props> = ({ ...props }) => {
if (Platform.isTV) return null;
const [settings, updateSettings] = useSettings(); const [settings, updateSettings] = useSettings();
const { t } = useTranslation(); const { t } = useTranslation();
if (!settings) return null; if (!settings) return null;
// todo: fix
if (Platform.isTV) return null;
return ( return (
<View> <View>
<ListGroup title={t("home.settings.languages.title")}> <ListGroup title={t("home.settings.languages.title")}>

View File

@@ -1,5 +1,5 @@
import { TouchableOpacity, View, ViewProps } from "react-native"; import { Platform, TouchableOpacity, View, ViewProps } from "react-native";
import * as DropdownMenu from "zeego/dropdown-menu"; const DropdownMenu = !Platform.isTV ? require("zeego/dropdown-menu") : null;
import { Text } from "../common/Text"; import { Text } from "../common/Text";
import { useMedia } from "./MediaContext"; import { useMedia } from "./MediaContext";
import { Switch } from "react-native-gesture-handler"; import { Switch } from "react-native-gesture-handler";
@@ -12,6 +12,7 @@ import { useSettings } from "@/utils/atoms/settings";
interface Props extends ViewProps {} interface Props extends ViewProps {}
export const AudioToggles: React.FC<Props> = ({ ...props }) => { export const AudioToggles: React.FC<Props> = ({ ...props }) => {
if (Platform.isTV) return null;
const media = useMedia(); const media = useMedia();
const [_, __, pluginSettings] = useSettings(); const [_, __, pluginSettings] = useSettings();
const { settings, updateSettings } = media; const { settings, updateSettings } = media;

View File

@@ -5,8 +5,8 @@ import { Ionicons } from "@expo/vector-icons";
import { useQueryClient } from "@tanstack/react-query"; import { useQueryClient } from "@tanstack/react-query";
import { useRouter } from "expo-router"; import { useRouter } from "expo-router";
import React, { useMemo } from "react"; import React, { useMemo } from "react";
import { Switch, TouchableOpacity } from "react-native"; import { Platform, Switch, TouchableOpacity } from "react-native";
import * as DropdownMenu from "zeego/dropdown-menu"; const DropdownMenu = !Platform.isTV ? require("zeego/dropdown-menu") : null;
import { Text } from "../common/Text"; import { Text } from "../common/Text";
import { ListGroup } from "../list/ListGroup"; import { ListGroup } from "../list/ListGroup";
import { ListItem } from "../list/ListItem"; import { ListItem } from "../list/ListItem";

View File

@@ -1,5 +1,5 @@
import { TouchableOpacity, View, ViewProps } from "react-native"; import { Platform, TouchableOpacity, View, ViewProps } from "react-native";
import * as DropdownMenu from "@/components/DropdownMenu"; const DropdownMenu = !Platform.isTV ? require("zeego/dropdown-menu") : null;
import { Text } from "../common/Text"; import { Text } from "../common/Text";
import { useMedia } from "./MediaContext"; import { useMedia } from "./MediaContext";
import { Switch } from "react-native-gesture-handler"; import { Switch } from "react-native-gesture-handler";
@@ -8,13 +8,14 @@ import { ListItem } from "../list/ListItem";
import { Ionicons } from "@expo/vector-icons"; import { Ionicons } from "@expo/vector-icons";
import { SubtitlePlaybackMode } from "@jellyfin/sdk/lib/generated-client"; import { SubtitlePlaybackMode } from "@jellyfin/sdk/lib/generated-client";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import {useSettings} from "@/utils/atoms/settings"; import { useSettings } from "@/utils/atoms/settings";
import {Stepper} from "@/components/inputs/Stepper"; import { Stepper } from "@/components/inputs/Stepper";
import Dropdown from "@/components/common/Dropdown"; import Dropdown from "@/components/common/Dropdown";
interface Props extends ViewProps {} interface Props extends ViewProps {}
export const SubtitleToggles: React.FC<Props> = ({ ...props }) => { export const SubtitleToggles: React.FC<Props> = ({ ...props }) => {
if (Platform.isTV) return null;
const media = useMedia(); const media = useMedia();
const [_, __, pluginSettings] = useSettings(); const [_, __, pluginSettings] = useSettings();
const { settings, updateSettings } = media; const { settings, updateSettings } = media;
@@ -34,7 +35,8 @@ export const SubtitleToggles: React.FC<Props> = ({ ...props }) => {
const subtitleModeKeys = { const subtitleModeKeys = {
[SubtitlePlaybackMode.Default]: "home.settings.subtitles.modes.Default", [SubtitlePlaybackMode.Default]: "home.settings.subtitles.modes.Default",
[SubtitlePlaybackMode.Smart]: "home.settings.subtitles.modes.Smart", [SubtitlePlaybackMode.Smart]: "home.settings.subtitles.modes.Smart",
[SubtitlePlaybackMode.OnlyForced]: "home.settings.subtitles.modes.OnlyForced", [SubtitlePlaybackMode.OnlyForced]:
"home.settings.subtitles.modes.OnlyForced",
[SubtitlePlaybackMode.Always]: "home.settings.subtitles.modes.Always", [SubtitlePlaybackMode.Always]: "home.settings.subtitles.modes.Always",
[SubtitlePlaybackMode.None]: "home.settings.subtitles.modes.None", [SubtitlePlaybackMode.None]: "home.settings.subtitles.modes.None",
}; };
@@ -51,13 +53,22 @@ export const SubtitleToggles: React.FC<Props> = ({ ...props }) => {
> >
<ListItem title={t("home.settings.subtitles.subtitle_language")}> <ListItem title={t("home.settings.subtitles.subtitle_language")}>
<Dropdown <Dropdown
data={[{DisplayName: t("home.settings.subtitles.none"), ThreeLetterISOLanguageName: "none-subs" },...(cultures ?? [])]} data={[
keyExtractor={(item) => item?.ThreeLetterISOLanguageName ?? "unknown"} {
DisplayName: t("home.settings.subtitles.none"),
ThreeLetterISOLanguageName: "none-subs",
},
...(cultures ?? []),
]}
keyExtractor={(item) =>
item?.ThreeLetterISOLanguageName ?? "unknown"
}
titleExtractor={(item) => item?.DisplayName} titleExtractor={(item) => item?.DisplayName}
title={ title={
<TouchableOpacity className="flex flex-row items-center justify-between py-3 pl-3"> <TouchableOpacity className="flex flex-row items-center justify-between py-3 pl-3">
<Text className="mr-1 text-[#8E8D91]"> <Text className="mr-1 text-[#8E8D91]">
{settings?.defaultSubtitleLanguage?.DisplayName || t("home.settings.subtitles.none")} {settings?.defaultSubtitleLanguage?.DisplayName ||
t("home.settings.subtitles.none")}
</Text> </Text>
<Ionicons <Ionicons
name="chevron-expand-sharp" name="chevron-expand-sharp"
@@ -69,11 +80,13 @@ export const SubtitleToggles: React.FC<Props> = ({ ...props }) => {
label={t("home.settings.subtitles.language")} label={t("home.settings.subtitles.language")}
onSelected={(defaultSubtitleLanguage) => onSelected={(defaultSubtitleLanguage) =>
updateSettings({ updateSettings({
defaultSubtitleLanguage: defaultSubtitleLanguage.DisplayName === t("home.settings.subtitles.none") defaultSubtitleLanguage:
? null defaultSubtitleLanguage.DisplayName ===
: defaultSubtitleLanguage t("home.settings.subtitles.none")
? null
: defaultSubtitleLanguage,
}) })
} }
/> />
</ListItem> </ListItem>
@@ -89,7 +102,8 @@ export const SubtitleToggles: React.FC<Props> = ({ ...props }) => {
title={ title={
<TouchableOpacity className="flex flex-row items-center justify-between py-3 pl-3"> <TouchableOpacity className="flex flex-row items-center justify-between py-3 pl-3">
<Text className="mr-1 text-[#8E8D91]"> <Text className="mr-1 text-[#8E8D91]">
{t(subtitleModeKeys[settings?.subtitleMode]) || t("home.settings.subtitles.loading")} {t(subtitleModeKeys[settings?.subtitleMode]) ||
t("home.settings.subtitles.loading")}
</Text> </Text>
<Ionicons <Ionicons
name="chevron-expand-sharp" name="chevron-expand-sharp"
@@ -99,9 +113,7 @@ export const SubtitleToggles: React.FC<Props> = ({ ...props }) => {
</TouchableOpacity> </TouchableOpacity>
} }
label={t("home.settings.subtitles.subtitle_mode")} label={t("home.settings.subtitles.subtitle_mode")}
onSelected={(subtitleMode) => onSelected={(subtitleMode) => updateSettings({ subtitleMode })}
updateSettings({subtitleMode})
}
/> />
</ListItem> </ListItem>
@@ -128,7 +140,7 @@ export const SubtitleToggles: React.FC<Props> = ({ ...props }) => {
step={5} step={5}
min={0} min={0}
max={120} max={120}
onUpdate={(subtitleSize) => updateSettings({subtitleSize})} onUpdate={(subtitleSize) => updateSettings({ subtitleSize })}
/> />
</ListItem> </ListItem>
</ListGroup> </ListGroup>

View File

@@ -31,7 +31,7 @@ import {
} from "@jellyfin/sdk/lib/generated-client"; } from "@jellyfin/sdk/lib/generated-client";
import { Image } from "expo-image"; import { Image } from "expo-image";
import { useLocalSearchParams, useRouter } from "expo-router"; import { useLocalSearchParams, useRouter } from "expo-router";
import * as ScreenOrientation from "expo-screen-orientation"; import * as ScreenOrientation from "@/packages/expo-screen-orientation";
import { useAtom } from "jotai"; import { useAtom } from "jotai";
import { debounce } from "lodash"; import { debounce } from "lodash";
import React, { useCallback, useEffect, useRef, useState } from "react"; import React, { useCallback, useEffect, useRef, useState } from "react";

View File

@@ -1,7 +1,7 @@
import React, { useMemo, useState } from "react"; import React, { useMemo, useState } from "react";
import { View, TouchableOpacity } from "react-native"; import { View, TouchableOpacity, Platform } from "react-native";
import { Ionicons } from "@expo/vector-icons"; import { Ionicons } from "@expo/vector-icons";
import * as DropdownMenu from "zeego/dropdown-menu"; const DropdownMenu = !Platform.isTV ? require("zeego/dropdown-menu") : null;
import { useControlContext } from "../contexts/ControlContext"; import { useControlContext } from "../contexts/ControlContext";
import { useVideoContext } from "../contexts/VideoContext"; import { useVideoContext } from "../contexts/VideoContext";
import { EmbeddedSubtitle, ExternalSubtitle } from "../types"; import { EmbeddedSubtitle, ExternalSubtitle } from "../types";

View File

@@ -1,7 +1,7 @@
import React, { useCallback, useMemo, useState } from "react"; import React, { useCallback, useMemo, useState } from "react";
import { View, TouchableOpacity } from "react-native"; import { View, TouchableOpacity, Platform } from "react-native";
import { Ionicons } from "@expo/vector-icons"; import { Ionicons } from "@expo/vector-icons";
import * as DropdownMenu from "zeego/dropdown-menu"; const DropdownMenu = !Platform.isTV ? require("zeego/dropdown-menu") : null;
import { useControlContext } from "../contexts/ControlContext"; import { useControlContext } from "../contexts/ControlContext";
import { useVideoContext } from "../contexts/VideoContext"; import { useVideoContext } from "../contexts/VideoContext";
import { TranscodedSubtitle } from "../types"; import { TranscodedSubtitle } from "../types";

View File

@@ -56,7 +56,7 @@
"expo-keep-awake": "~13.0.2", "expo-keep-awake": "~13.0.2",
"expo-linear-gradient": "~13.0.2", "expo-linear-gradient": "~13.0.2",
"expo-linking": "~6.3.1", "expo-linking": "~6.3.1",
"expo-localization": "~15.0.3", "expo-localization": "~16.0.1",
"expo-network": "~6.0.1", "expo-network": "~6.0.1",
"expo-notifications": "~0.28.19", "expo-notifications": "~0.28.19",
"expo-router": "~3.5.24", "expo-router": "~3.5.24",

View File

@@ -1,6 +1,6 @@
import { atom, useAtom } from "jotai"; import { atom, useAtom } from "jotai";
import { useCallback, useEffect, useMemo } from "react"; import { useCallback, useEffect, useMemo } from "react";
import * as ScreenOrientation from "expo-screen-orientation"; import * as ScreenOrientation from "@/packages/expo-screen-orientation";
import { storage } from "../mmkv"; import { storage } from "../mmkv";
import { Platform } from "react-native"; import { Platform } from "react-native";
import { import {