mirror of
https://github.com/streamyfin/streamyfin.git
synced 2026-04-21 16:24:41 +01:00
Settings Fields V
This commit is contained in:
@@ -3,6 +3,7 @@ import * as DropdownMenu from "zeego/dropdown-menu";
|
||||
import { Text } from "../common/Text";
|
||||
import { useMedia } from "./MediaContext";
|
||||
import { Switch } from "react-native-gesture-handler";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
interface Props extends ViewProps {}
|
||||
|
||||
@@ -10,12 +11,13 @@ export const AudioToggles: React.FC<Props> = ({ ...props }) => {
|
||||
const media = useMedia();
|
||||
const { settings, updateSettings } = media;
|
||||
const cultures = media.cultures;
|
||||
const { t } = useTranslation();
|
||||
|
||||
if (!settings) return null;
|
||||
|
||||
return (
|
||||
<View>
|
||||
<Text className="text-lg font-bold mb-2">Audio</Text>
|
||||
<Text className="text-lg font-bold mb-2">{t("home.settings.audio.audio_title")}</Text>
|
||||
<View className="flex flex-col rounded-xl mb-4 overflow-hidden divide-y-2 divide-solid divide-neutral-800">
|
||||
<View
|
||||
className={`
|
||||
@@ -23,9 +25,9 @@ export const AudioToggles: React.FC<Props> = ({ ...props }) => {
|
||||
`}
|
||||
>
|
||||
<View className="flex flex-col shrink">
|
||||
<Text className="font-semibold">Audio language</Text>
|
||||
<Text className="font-semibold">{t("home.settings.audio.audio_language")}</Text>
|
||||
<Text className="text-xs opacity-50">
|
||||
Choose a default audio language.
|
||||
{t("home.settings.audio.audio_language_hint")}
|
||||
</Text>
|
||||
</View>
|
||||
<DropdownMenu.Root>
|
||||
@@ -76,9 +78,9 @@ export const AudioToggles: React.FC<Props> = ({ ...props }) => {
|
||||
<View className="flex flex-col">
|
||||
<View className="flex flex-row items-center justify-between bg-neutral-900 p-4">
|
||||
<View className="flex flex-col">
|
||||
<Text className="font-semibold">Use Default Audio</Text>
|
||||
<Text className="font-semibold">{t("home.settings.audio.use_default_audio")}</Text>
|
||||
<Text className="text-xs opacity-50">
|
||||
Play default audio track regardless of language.
|
||||
{t("home.settings.audio.use_default_audio_hint")}
|
||||
</Text>
|
||||
</View>
|
||||
<Switch
|
||||
@@ -93,11 +95,10 @@ export const AudioToggles: React.FC<Props> = ({ ...props }) => {
|
||||
<View className="flex flex-row items-center justify-between bg-neutral-900 p-4">
|
||||
<View className="flex flex-col">
|
||||
<Text className="font-semibold">
|
||||
Set Audio Track From Previous Item
|
||||
{t("home.settings.audio.set_audio_track")}
|
||||
</Text>
|
||||
<Text className="text-xs opacity-50 min max-w-[85%]">
|
||||
Try to set the audio track to the closest match to the last
|
||||
video.
|
||||
{t("home.settings.audio.set_audio_track_hint")}
|
||||
</Text>
|
||||
</View>
|
||||
<Switch
|
||||
|
||||
@@ -11,6 +11,7 @@ import { apiAtom, userAtom } from "@/providers/JellyfinProvider";
|
||||
import { useAtom } from "jotai";
|
||||
import { toast } from "sonner-native";
|
||||
import { useMutation } from "@tanstack/react-query";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
export const JellyseerrSettings = () => {
|
||||
const {
|
||||
@@ -20,6 +21,8 @@ export const JellyseerrSettings = () => {
|
||||
clearAllJellyseerData,
|
||||
} = useJellyseerr();
|
||||
|
||||
const { t } = useTranslation();
|
||||
|
||||
const [user] = useAtom(userAtom);
|
||||
const [settings, updateSettings] = useSettings();
|
||||
|
||||
@@ -121,19 +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">
|
||||
This integration is in its early stages. Expect things to change.
|
||||
{t("home.settings.jellyseer.jellyseer_warning")}
|
||||
</Text>
|
||||
<Text className="font-bold mb-1">Server URL</Text>
|
||||
<Text className="font-bold mb-1">{t("home.settings.jellyseer.server_url")}</Text>
|
||||
<View className="flex flex-col shrink mb-2">
|
||||
<Text className="text-xs text-gray-600">
|
||||
Example: http(s)://your-host.url
|
||||
</Text>
|
||||
<Text className="text-xs text-gray-600">
|
||||
(add port if required)
|
||||
{t("home.settings.jellyseer.server_url_hint")}
|
||||
</Text>
|
||||
</View>
|
||||
<Input
|
||||
placeholder="Jellyseerr URL..."
|
||||
placeholder={t("home.settings.jellyseer.server_url_placeholder")}
|
||||
value={settings?.jellyseerrServerUrl ?? jellyseerrServerUrl}
|
||||
defaultValue={
|
||||
settings?.jellyseerrServerUrl ?? jellyseerrServerUrl
|
||||
@@ -163,7 +163,7 @@ export const JellyseerrSettings = () => {
|
||||
marginBottom: 8,
|
||||
}}
|
||||
>
|
||||
{promptForJellyseerrPass ? "Clear" : "Save"}
|
||||
{promptForJellyseerrPass ? t("home.settings.jellyseer.clear_button") : t("home.settings.jellyseer.save_button")}
|
||||
</Button>
|
||||
|
||||
<View
|
||||
@@ -172,11 +172,11 @@ export const JellyseerrSettings = () => {
|
||||
opacity: promptForJellyseerrPass ? 1 : 0.5,
|
||||
}}
|
||||
>
|
||||
<Text className="font-bold mb-2">Password</Text>
|
||||
<Text className="font-bold mb-2">{t("home.settings.jellyseer.password")}</Text>
|
||||
<Input
|
||||
autoFocus={true}
|
||||
focusable={true}
|
||||
placeholder={`Enter password for Jellyfin user ${user?.Name}`}
|
||||
placeholder={t("home.settings.jellyseer.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()}
|
||||
>
|
||||
Login
|
||||
{t("home.settings.jellyseer.login_button")}
|
||||
</Button>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
@@ -1,17 +1,19 @@
|
||||
import { useSettings } from "@/utils/atoms/settings";
|
||||
import { TouchableOpacity, View, ViewProps } from "react-native";
|
||||
import { Text } from "../common/Text";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
interface Props extends ViewProps {}
|
||||
|
||||
export const MediaToggles: React.FC<Props> = ({ ...props }) => {
|
||||
const [settings, updateSettings] = useSettings();
|
||||
const { t } = useTranslation();
|
||||
|
||||
if (!settings) return null;
|
||||
|
||||
return (
|
||||
<View>
|
||||
<Text className="text-lg font-bold mb-2">Media</Text>
|
||||
<Text className="text-lg font-bold mb-2">{t("home.settings.media.media_title")}</Text>
|
||||
<View className="flex flex-col rounded-xl mb-4 overflow-hidden divide-y-2 divide-solid divide-neutral-800">
|
||||
<View
|
||||
className={`
|
||||
@@ -19,9 +21,9 @@ export const MediaToggles: React.FC<Props> = ({ ...props }) => {
|
||||
`}
|
||||
>
|
||||
<View className="flex flex-col shrink">
|
||||
<Text className="font-semibold">Forward skip length</Text>
|
||||
<Text className="font-semibold">{t("home.settings.media.forward_skip_length")}</Text>
|
||||
<Text className="text-xs opacity-50">
|
||||
Choose length in seconds when skipping in video playback.
|
||||
{t("home.settings.media.forward_skip_length_hint")}
|
||||
</Text>
|
||||
</View>
|
||||
<View className="flex flex-row items-center">
|
||||
@@ -57,9 +59,9 @@ export const MediaToggles: React.FC<Props> = ({ ...props }) => {
|
||||
`}
|
||||
>
|
||||
<View className="flex flex-col shrink">
|
||||
<Text className="font-semibold">Rewind length</Text>
|
||||
<Text className="font-semibold">{t("home.settings.media.rewind_length")}</Text>
|
||||
<Text className="text-xs opacity-50">
|
||||
Choose length in seconds when skipping in video playback.
|
||||
{t("home.settings.media.rewind_length_hint")}
|
||||
</Text>
|
||||
</View>
|
||||
<View className="flex flex-row items-center">
|
||||
|
||||
@@ -43,6 +43,7 @@ import { AudioToggles } from "./AudioToggles";
|
||||
import { JellyseerrApi, useJellyseerr } from "@/hooks/useJellyseerr";
|
||||
import { ListItem } from "@/components/ListItem";
|
||||
import { JellyseerrSettings } from "./Jellyseerr";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
interface Props extends ViewProps {}
|
||||
|
||||
@@ -59,6 +60,8 @@ export const SettingToggles: React.FC<Props> = ({ ...props }) => {
|
||||
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
const { t } = useTranslation();
|
||||
|
||||
/********************
|
||||
* Background task
|
||||
*******************/
|
||||
@@ -137,15 +140,14 @@ export const SettingToggles: React.FC<Props> = ({ ...props }) => {
|
||||
</MediaProvider>
|
||||
|
||||
<View>
|
||||
<Text className="text-lg font-bold mb-2">Other</Text>
|
||||
<Text className="text-lg font-bold mb-2">{t("home.settings.other.other_title")}</Text>
|
||||
|
||||
<View className="flex flex-col rounded-xl overflow-hidden divide-y-2 divide-solid divide-neutral-800">
|
||||
<View className="flex flex-row items-center justify-between bg-neutral-900 p-4">
|
||||
<View className="shrink">
|
||||
<Text className="font-semibold">Auto rotate</Text>
|
||||
<Text className="font-semibold">{t("home.settings.other.auto_rotate")}</Text>
|
||||
<Text className="text-xs opacity-50">
|
||||
Important on android since the video player orientation is
|
||||
locked to the app orientation.
|
||||
{t("home.settings.other.auto_rotate_hint")}
|
||||
</Text>
|
||||
</View>
|
||||
<Switch
|
||||
@@ -166,9 +168,9 @@ export const SettingToggles: React.FC<Props> = ({ ...props }) => {
|
||||
`}
|
||||
>
|
||||
<View className="flex flex-col shrink">
|
||||
<Text className="font-semibold">Video orientation</Text>
|
||||
<Text className="font-semibold">{t("home.settings.other.video_orientation")}</Text>
|
||||
<Text className="text-xs opacity-50">
|
||||
Set the full screen video player orientation.
|
||||
{t("home.settings.other.video_orientation_hint")}
|
||||
</Text>
|
||||
</View>
|
||||
<DropdownMenu.Root>
|
||||
@@ -263,9 +265,9 @@ export const SettingToggles: React.FC<Props> = ({ ...props }) => {
|
||||
|
||||
<View className="flex flex-row items-center justify-between bg-neutral-900 p-4">
|
||||
<View className="shrink">
|
||||
<Text className="font-semibold">Safe area in controls</Text>
|
||||
<Text className="font-semibold">{t("home.settings.other.safe_area_in_controls")}</Text>
|
||||
<Text className="text-xs opacity-50">
|
||||
Enable safe area in video player controls
|
||||
{t("home.settings.other.safe_area_in_controls_hint")}
|
||||
</Text>
|
||||
</View>
|
||||
<Switch
|
||||
@@ -279,8 +281,8 @@ export const SettingToggles: React.FC<Props> = ({ ...props }) => {
|
||||
<View className="flex flex-col">
|
||||
<View className="flex flex-row items-center justify-between bg-neutral-900 p-4">
|
||||
<View className="flex flex-col">
|
||||
<Text className="font-semibold">Use popular lists plugin</Text>
|
||||
<Text className="text-xs opacity-50">Made by: lostb1t</Text>
|
||||
<Text className="font-semibold">{t("home.settings.other.use_popular_lists_plugin")}</Text>
|
||||
<Text className="text-xs opacity-50">{t("home.settings.other.use_popular_lists_plugin_hint")}</Text>
|
||||
<TouchableOpacity
|
||||
onPress={() => {
|
||||
Linking.openURL(
|
||||
@@ -288,7 +290,7 @@ export const SettingToggles: React.FC<Props> = ({ ...props }) => {
|
||||
);
|
||||
}}
|
||||
>
|
||||
<Text className="text-xs text-purple-600">More info</Text>
|
||||
<Text className="text-xs text-purple-600">{t("home.settings.other.more_info")}</Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
<Switch
|
||||
@@ -353,9 +355,9 @@ export const SettingToggles: React.FC<Props> = ({ ...props }) => {
|
||||
`}
|
||||
>
|
||||
<View className="flex flex-col shrink">
|
||||
<Text className="font-semibold">Search engine</Text>
|
||||
<Text className="font-semibold">{t("home.settings.other.search_engine")}</Text>
|
||||
<Text className="text-xs opacity-50">
|
||||
Choose the search engine you want to use.
|
||||
{t("home.settings.other.search_engine_hint")}
|
||||
</Text>
|
||||
</View>
|
||||
<DropdownMenu.Root>
|
||||
@@ -421,7 +423,7 @@ export const SettingToggles: React.FC<Props> = ({ ...props }) => {
|
||||
});
|
||||
}}
|
||||
>
|
||||
Save
|
||||
{t("home.settings.other.save_button")}
|
||||
</Button>
|
||||
</View>
|
||||
|
||||
@@ -436,10 +438,9 @@ export const SettingToggles: React.FC<Props> = ({ ...props }) => {
|
||||
|
||||
<View className="flex flex-row items-center justify-between bg-neutral-900 p-4">
|
||||
<View className="shrink">
|
||||
<Text className="font-semibold">Show Custom Menu Links</Text>
|
||||
<Text className="font-semibold">{t("home.settings.other.show_custom_menu_links")}</Text>
|
||||
<Text className="text-xs opacity-50">
|
||||
Show custom menu links defined inside your Jellyfin web
|
||||
config.json file
|
||||
{t("home.settings.other.show_custom_menu_links_hint")}
|
||||
</Text>
|
||||
<TouchableOpacity
|
||||
onPress={() =>
|
||||
@@ -448,7 +449,7 @@ export const SettingToggles: React.FC<Props> = ({ ...props }) => {
|
||||
)
|
||||
}
|
||||
>
|
||||
<Text className="text-xs text-purple-600">More info</Text>
|
||||
<Text className="text-xs text-purple-600">{t("home.settings.other.more_info")}</Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
<Switch
|
||||
@@ -462,7 +463,7 @@ export const SettingToggles: React.FC<Props> = ({ ...props }) => {
|
||||
</View>
|
||||
|
||||
<View className="mt-4">
|
||||
<Text className="text-lg font-bold mb-2">Downloads</Text>
|
||||
<Text className="text-lg font-bold mb-2">{t("home.settings.downloads.downloads_title")}</Text>
|
||||
<View className="flex flex-col rounded-xl overflow-hidden divide-y-2 divide-solid divide-neutral-800">
|
||||
<View
|
||||
className={`
|
||||
@@ -470,10 +471,9 @@ export const SettingToggles: React.FC<Props> = ({ ...props }) => {
|
||||
`}
|
||||
>
|
||||
<View className="flex flex-col shrink">
|
||||
<Text className="font-semibold">Download method</Text>
|
||||
<Text className="font-semibold">{t("home.settings.downloads.download_method")}</Text>
|
||||
<Text className="text-xs opacity-50">
|
||||
Choose the download method to use. Optimized requires the
|
||||
optimized server.
|
||||
{t("home.settings.downloads.download_method_hint")}
|
||||
</Text>
|
||||
</View>
|
||||
<DropdownMenu.Root>
|
||||
@@ -531,10 +531,9 @@ export const SettingToggles: React.FC<Props> = ({ ...props }) => {
|
||||
}`}
|
||||
>
|
||||
<View className="flex flex-col shrink">
|
||||
<Text className="font-semibold">Remux max download</Text>
|
||||
<Text className="font-semibold">{t("home.settings.downloads.remux_max_download")}</Text>
|
||||
<Text className="text-xs opacity-50 shrink">
|
||||
This is the total media you want to be able to download at the
|
||||
same time.
|
||||
{t("home.settings.downloads.remux_max_download_hint")}
|
||||
</Text>
|
||||
</View>
|
||||
<Stepper
|
||||
@@ -563,10 +562,9 @@ export const SettingToggles: React.FC<Props> = ({ ...props }) => {
|
||||
}`}
|
||||
>
|
||||
<View className="flex flex-col shrink">
|
||||
<Text className="font-semibold">Auto download</Text>
|
||||
<Text className="font-semibold">{t("home.settings.downloads.auto_download")}</Text>
|
||||
<Text className="text-xs opacity-50 shrink">
|
||||
This will automatically download the media file when it's
|
||||
finished optimizing on the server.
|
||||
{t("home.settings.downloads.auto_download_hint")}
|
||||
</Text>
|
||||
</View>
|
||||
<Switch
|
||||
@@ -589,11 +587,11 @@ export const SettingToggles: React.FC<Props> = ({ ...props }) => {
|
||||
<View className="flex flex-col shrink mb-2">
|
||||
<View className="flex flex-row justify-between items-center">
|
||||
<Text className="font-semibold">
|
||||
Optimized versions server
|
||||
{t("home.settings.downloads.optimized_versions_server")}
|
||||
</Text>
|
||||
</View>
|
||||
<Text className="text-xs opacity-50">
|
||||
Set the URL for the optimized versions server for downloads.
|
||||
{t("home.settings.downloads.optimized_versions_server_hint")}
|
||||
</Text>
|
||||
</View>
|
||||
<View></View>
|
||||
@@ -629,7 +627,7 @@ export const SettingToggles: React.FC<Props> = ({ ...props }) => {
|
||||
} else toast.error("Could not connect");
|
||||
}}
|
||||
>
|
||||
Save
|
||||
{t("home.settings.downloads.save_button")}
|
||||
</Button>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
@@ -4,6 +4,7 @@ import { Text } from "../common/Text";
|
||||
import { useMedia } from "./MediaContext";
|
||||
import { Switch } from "react-native-gesture-handler";
|
||||
import { SubtitlePlaybackMode } from "@jellyfin/sdk/lib/generated-client";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
interface Props extends ViewProps {}
|
||||
|
||||
@@ -11,6 +12,8 @@ export const SubtitleToggles: React.FC<Props> = ({ ...props }) => {
|
||||
const media = useMedia();
|
||||
const { settings, updateSettings } = media;
|
||||
const cultures = media.cultures;
|
||||
const { t } = useTranslation();
|
||||
|
||||
if (!settings) return null;
|
||||
|
||||
const subtitleModes = [
|
||||
@@ -23,7 +26,7 @@ export const SubtitleToggles: React.FC<Props> = ({ ...props }) => {
|
||||
|
||||
return (
|
||||
<View>
|
||||
<Text className="text-lg font-bold mb-2">Subtitle</Text>
|
||||
<Text className="text-lg font-bold mb-2">{t("home.settings.subtitles.subtitle_title")}</Text>
|
||||
<View className="flex flex-col rounded-xl mb-4 overflow-hidden divide-y-2 divide-solid divide-neutral-800">
|
||||
<View
|
||||
className={`
|
||||
@@ -31,9 +34,9 @@ export const SubtitleToggles: React.FC<Props> = ({ ...props }) => {
|
||||
`}
|
||||
>
|
||||
<View className="flex flex-col shrink">
|
||||
<Text className="font-semibold">Subtitle language</Text>
|
||||
<Text className="font-semibold">{t("home.settings.subtitles.subtitle_language")}</Text>
|
||||
<Text className="text-xs opacity-50">
|
||||
Choose a default subtitle language.
|
||||
{t("home.settings.subtitles.subtitle_language_hint")}
|
||||
</Text>
|
||||
</View>
|
||||
<DropdownMenu.Root>
|
||||
@@ -88,11 +91,9 @@ export const SubtitleToggles: React.FC<Props> = ({ ...props }) => {
|
||||
`}
|
||||
>
|
||||
<View className="flex flex-col shrink">
|
||||
<Text className="font-semibold">Subtitle Mode</Text>
|
||||
<Text className="font-semibold">{t("home.settings.subtitles.subtitle_mode")}</Text>
|
||||
<Text className="text-xs opacity-50 mr-2">
|
||||
Subtitles are loaded based on the default and forced flags in the
|
||||
embedded metadata. Language preferences are considered when
|
||||
multiple options are available.
|
||||
{t("home.settings.subtitles.subtitle_mode_hint")}
|
||||
</Text>
|
||||
</View>
|
||||
<DropdownMenu.Root>
|
||||
@@ -131,11 +132,10 @@ export const SubtitleToggles: React.FC<Props> = ({ ...props }) => {
|
||||
<View className="flex flex-row items-center justify-between bg-neutral-900 p-4">
|
||||
<View className="flex flex-col">
|
||||
<Text className="font-semibold">
|
||||
Set Subtitle Track From Previous Item
|
||||
{t("home.settings.subtitles.set_subtitle_track")}
|
||||
</Text>
|
||||
<Text className="text-xs opacity-50 min max-w-[85%]">
|
||||
Try to set the subtitle track to the closest match to the last
|
||||
video.
|
||||
{t("home.settings.subtitles.set_subtitle_track_hint")}
|
||||
</Text>
|
||||
</View>
|
||||
<Switch
|
||||
@@ -153,10 +153,9 @@ export const SubtitleToggles: React.FC<Props> = ({ ...props }) => {
|
||||
`}
|
||||
>
|
||||
<View className="flex flex-col shrink">
|
||||
<Text className="font-semibold">Subtitle Size</Text>
|
||||
<Text className="font-semibold">{t("home.settings.subtitles.subtitle_size")}</Text>
|
||||
<Text className="text-xs opacity-50">
|
||||
Choose a default subtitle size for direct play (only works for
|
||||
some subtitle formats).
|
||||
{t("home.settings.subtitles.subtitle_size_hint")}
|
||||
</Text>
|
||||
</View>
|
||||
<View className="flex flex-row items-center">
|
||||
|
||||
Reference in New Issue
Block a user