mirror of
https://github.com/streamyfin/streamyfin.git
synced 2026-04-23 17:24:42 +01:00
first commit
This commit is contained in:
@@ -42,11 +42,17 @@ export default function IndexLayout() {
|
||||
}}
|
||||
/>
|
||||
<Stack.Screen
|
||||
name="settings"
|
||||
name="settings/index"
|
||||
options={{
|
||||
title: "Settings",
|
||||
}}
|
||||
/>
|
||||
<Stack.Screen
|
||||
name="settings/audio-language"
|
||||
options={{
|
||||
title: "Audio Language",
|
||||
}}
|
||||
/>
|
||||
{Object.entries(nestedTabPageScreenOptions).map(([name, options]) => (
|
||||
<Stack.Screen key={name} name={name} options={options} />
|
||||
))}
|
||||
|
||||
61
app/(auth)/(tabs)/(home)/settings/audio-language.tsx
Normal file
61
app/(auth)/(tabs)/(home)/settings/audio-language.tsx
Normal file
@@ -0,0 +1,61 @@
|
||||
import { ScrollView, View, ViewProps } from "react-native";
|
||||
import { Text } from "@/components/common/Text";
|
||||
import { useSafeAreaInsets } from "react-native-safe-area-context";
|
||||
import { LANGUAGES } from "@/constants/Languages";
|
||||
import { ListItem } from "@/components/list/ListItem";
|
||||
import { ListSection } from "@/components/list/ListSection";
|
||||
import { TAB_HEIGHT } from "@/constants/Values";
|
||||
import { DefaultLanguageOption, useSettings } from "@/utils/atoms/settings";
|
||||
import { Ionicons } from "@expo/vector-icons";
|
||||
import { Colors } from "@/constants/Colors";
|
||||
|
||||
interface Props extends ViewProps {}
|
||||
|
||||
export default function page() {
|
||||
const insets = useSafeAreaInsets();
|
||||
const [settings, updateSettings] = useSettings();
|
||||
return (
|
||||
<ScrollView
|
||||
contentContainerStyle={{
|
||||
paddingLeft: insets.left,
|
||||
paddingRight: insets.right,
|
||||
paddingBottom: 16,
|
||||
}}
|
||||
style={{
|
||||
marginBottom: TAB_HEIGHT,
|
||||
}}
|
||||
>
|
||||
<View className="py-4 px-4">
|
||||
<ListSection title="LANGUAGES">
|
||||
{LANGUAGES.sort(sortByName).map((l) => (
|
||||
<ListItem
|
||||
key={l.value}
|
||||
title={l.label}
|
||||
onPress={() => {
|
||||
updateSettings({
|
||||
...settings,
|
||||
defaultAudioLanguage: l,
|
||||
});
|
||||
}}
|
||||
iconAfter={
|
||||
settings?.defaultAudioLanguage?.value === l.value ? (
|
||||
<Ionicons name="checkmark" size={24} color={Colors.primary} />
|
||||
) : null
|
||||
}
|
||||
/>
|
||||
))}
|
||||
</ListSection>
|
||||
</View>
|
||||
</ScrollView>
|
||||
);
|
||||
}
|
||||
|
||||
const sortByName = (a: DefaultLanguageOption, b: DefaultLanguageOption) => {
|
||||
if (a.label < b.label) {
|
||||
return -1;
|
||||
}
|
||||
if (a.label > b.label) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
};
|
||||
@@ -1,13 +1,18 @@
|
||||
import { Button } from "@/components/Button";
|
||||
import { Text } from "@/components/common/Text";
|
||||
import { ListItem } from "@/components/ListItem";
|
||||
import { ListInputItem } from "@/components/list/ListInputItem";
|
||||
import { ListItem } from "@/components/list/ListItem";
|
||||
import { ListSection } from "@/components/list/ListSection";
|
||||
import { SettingToggles } from "@/components/settings/SettingToggles";
|
||||
import { useDownload } from "@/providers/DownloadProvider";
|
||||
import { apiAtom, useJellyfin, userAtom } from "@/providers/JellyfinProvider";
|
||||
import { useSettings } from "@/utils/atoms/settings";
|
||||
import { clearLogs, readFromLog } from "@/utils/log";
|
||||
import { Ionicons } from "@expo/vector-icons";
|
||||
import { getQuickConnectApi } from "@jellyfin/sdk/lib/utils/api";
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
import * as Haptics from "expo-haptics";
|
||||
import { useRouter } from "expo-router";
|
||||
import { useAtom } from "jotai";
|
||||
import { Alert, ScrollView, View } from "react-native";
|
||||
import { useSafeAreaInsets } from "react-native-safe-area-context";
|
||||
@@ -16,6 +21,7 @@ import { toast } from "sonner-native";
|
||||
export default function settings() {
|
||||
const { logout } = useJellyfin();
|
||||
const { deleteAllFiles } = useDownload();
|
||||
const [settings, updateSettings] = useSettings();
|
||||
|
||||
const [api] = useAtom(apiAtom);
|
||||
const [user] = useAtom(userAtom);
|
||||
@@ -57,6 +63,8 @@ export default function settings() {
|
||||
);
|
||||
};
|
||||
|
||||
const router = useRouter();
|
||||
|
||||
return (
|
||||
<ScrollView
|
||||
contentContainerStyle={{
|
||||
@@ -73,15 +81,46 @@ export default function settings() {
|
||||
>
|
||||
registerBackgroundFetchAsync
|
||||
</Button> */}
|
||||
<View>
|
||||
<Text className="font-bold text-lg mb-2">User Info</Text>
|
||||
<ListSection title="USER INFO">
|
||||
<ListItem title="User" text={user?.Name} />
|
||||
<ListItem title="Server" text={api?.basePath} />
|
||||
<ListItem title="Token" text={api?.accessToken} />
|
||||
</ListSection>
|
||||
|
||||
<View className="flex flex-col rounded-xl overflow-hidden border-neutral-800 divide-y-2 divide-solid divide-neutral-800 ">
|
||||
<ListItem title="User" subTitle={user?.Name} />
|
||||
<ListItem title="Server" subTitle={api?.basePath} />
|
||||
<ListItem title="Token" subTitle={api?.accessToken} />
|
||||
</View>
|
||||
</View>
|
||||
<ListSection title="MEDIA">
|
||||
<ListItem
|
||||
title="Audio language"
|
||||
iconAfter={
|
||||
<Ionicons name="chevron-forward" size={20} color="white" />
|
||||
}
|
||||
onPress={() => router.push("/settings/audio-language")}
|
||||
/>
|
||||
<ListItem
|
||||
title="Subtitle language"
|
||||
iconAfter={
|
||||
<Ionicons name="chevron-forward" size={20} color="white" />
|
||||
}
|
||||
onPress={() => router.push("/settings/subtitle-language")}
|
||||
/>
|
||||
<ListInputItem
|
||||
textInputProps={{
|
||||
placeholder: "30",
|
||||
clearButtonMode: "never",
|
||||
returnKeyType: "done",
|
||||
}}
|
||||
defaultValue={(settings?.forwardSkipTime || "").toString()}
|
||||
title={"Forward skip"}
|
||||
onChange={(val) => {
|
||||
// 1. validate positive number
|
||||
// 2. save settings
|
||||
if (val.length === 0) return;
|
||||
if (val.match(/^\d+$/)) {
|
||||
} else {
|
||||
toast.error("Invalid number");
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</ListSection>
|
||||
|
||||
<View>
|
||||
<Text className="font-bold text-lg mb-2">Quick connect</Text>
|
||||
61
app/(auth)/(tabs)/(home)/settings/subtitle-language.tsx
Normal file
61
app/(auth)/(tabs)/(home)/settings/subtitle-language.tsx
Normal file
@@ -0,0 +1,61 @@
|
||||
import { ScrollView, View, ViewProps } from "react-native";
|
||||
import { Text } from "@/components/common/Text";
|
||||
import { useSafeAreaInsets } from "react-native-safe-area-context";
|
||||
import { LANGUAGES } from "@/constants/Languages";
|
||||
import { ListItem } from "@/components/list/ListItem";
|
||||
import { ListSection } from "@/components/list/ListSection";
|
||||
import { TAB_HEIGHT } from "@/constants/Values";
|
||||
import { DefaultLanguageOption, useSettings } from "@/utils/atoms/settings";
|
||||
import { Ionicons } from "@expo/vector-icons";
|
||||
import { Colors } from "@/constants/Colors";
|
||||
|
||||
interface Props extends ViewProps {}
|
||||
|
||||
export default function page() {
|
||||
const insets = useSafeAreaInsets();
|
||||
const [settings, updateSettings] = useSettings();
|
||||
return (
|
||||
<ScrollView
|
||||
contentContainerStyle={{
|
||||
paddingLeft: insets.left,
|
||||
paddingRight: insets.right,
|
||||
paddingBottom: 16,
|
||||
}}
|
||||
style={{
|
||||
marginBottom: TAB_HEIGHT,
|
||||
}}
|
||||
>
|
||||
<View className="py-4 px-4">
|
||||
<ListSection title="LANGUAGES">
|
||||
{LANGUAGES.sort(sortByName).map((l) => (
|
||||
<ListItem
|
||||
key={l.value}
|
||||
title={l.label}
|
||||
onPress={() => {
|
||||
updateSettings({
|
||||
...settings,
|
||||
defaultSubtitleLanguage: l,
|
||||
});
|
||||
}}
|
||||
iconAfter={
|
||||
settings?.defaultSubtitleLanguage?.value === l.value ? (
|
||||
<Ionicons name="checkmark" size={24} color={Colors.primary} />
|
||||
) : null
|
||||
}
|
||||
/>
|
||||
))}
|
||||
</ListSection>
|
||||
</View>
|
||||
</ScrollView>
|
||||
);
|
||||
}
|
||||
|
||||
const sortByName = (a: DefaultLanguageOption, b: DefaultLanguageOption) => {
|
||||
if (a.label < b.label) {
|
||||
return -1;
|
||||
}
|
||||
if (a.label > b.label) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
};
|
||||
Reference in New Issue
Block a user