chore: remove deps

This commit is contained in:
Fredrik Burmester
2025-01-04 17:08:00 +01:00
parent 8ea38a3efc
commit aa785b0f95
18 changed files with 1248 additions and 909 deletions

View File

@@ -1,8 +1,9 @@
import { TouchableOpacity, View, ViewProps } from "react-native";
import * as DropdownMenu from "zeego/dropdown-menu";
import { TouchableOpacity, View, ViewProps, Modal } from "react-native";
import { Text } from "../common/Text";
import { useMedia } from "./MediaContext";
import { Switch } from "react-native-gesture-handler";
import { Ionicons } from "@expo/vector-icons";
import { useState } from "react";
interface Props extends ViewProps {}
@@ -10,69 +11,35 @@ export const AudioToggles: React.FC<Props> = ({ ...props }) => {
const media = useMedia();
const { settings, updateSettings } = media;
const cultures = media.cultures;
const [isModalVisible, setIsModalVisible] = useState(false);
if (!settings) return null;
return (
<View>
<Text className="text-lg font-bold mb-2">Audio</Text>
<View className="flex flex-col rounded-xl mb-4 overflow-hidden divide-y-2 divide-solid divide-neutral-800">
<View
className={`
flex flex-row items-center space-x-2 justify-between bg-neutral-900 p-4
`}
>
<View className="flex flex-col rounded-xl mb-4 overflow-hidden divide-y-2 divide-solid divide-neutral-800">
<View className="flex flex-row items-center space-x-2 justify-between bg-neutral-900 p-4">
<View className="flex flex-col shrink">
<Text className="font-semibold">Audio language</Text>
<Text className="text-xs opacity-50">
Choose a default audio language.
</Text>
</View>
<DropdownMenu.Root>
<DropdownMenu.Trigger>
<TouchableOpacity className="bg-neutral-800 rounded-lg border-neutral-900 border px-3 py-2 flex flex-row items-center justify-between">
<Text>
{settings?.defaultAudioLanguage?.DisplayName || "None"}
</Text>
</TouchableOpacity>
</DropdownMenu.Trigger>
<DropdownMenu.Content
loop={true}
side="bottom"
align="start"
alignOffset={0}
avoidCollisions={true}
collisionPadding={8}
sideOffset={8}
>
<DropdownMenu.Label>Languages</DropdownMenu.Label>
<DropdownMenu.Item
key={"none-audio"}
onSelect={() => {
updateSettings({
defaultAudioLanguage: null,
});
}}
>
<DropdownMenu.ItemTitle>None</DropdownMenu.ItemTitle>
</DropdownMenu.Item>
{cultures?.map((l) => (
<DropdownMenu.Item
key={l?.ThreeLetterISOLanguageName ?? "unknown"}
onSelect={() => {
updateSettings({
defaultAudioLanguage: l,
});
}}
>
<DropdownMenu.ItemTitle>
{l.DisplayName}
</DropdownMenu.ItemTitle>
</DropdownMenu.Item>
))}
</DropdownMenu.Content>
</DropdownMenu.Root>
<TouchableOpacity
className="bg-neutral-800 rounded-lg border-neutral-900 border px-3 py-2 flex flex-row items-center justify-between"
onPress={() => setIsModalVisible(true)}
>
<Text>{settings?.defaultAudioLanguage?.DisplayName || "None"}</Text>
<Ionicons
name="chevron-down"
size={16}
color="white"
style={{ opacity: 0.5, marginLeft: 8 }}
/>
</TouchableOpacity>
</View>
<View className="flex flex-col">
<View className="flex flex-row items-center justify-between bg-neutral-900 p-4">
<View className="flex flex-col">
@@ -89,6 +56,7 @@ export const AudioToggles: React.FC<Props> = ({ ...props }) => {
/>
</View>
</View>
<View className="flex flex-col">
<View className="flex flex-row items-center justify-between bg-neutral-900 p-4">
<View className="flex flex-col">
@@ -109,6 +77,71 @@ export const AudioToggles: React.FC<Props> = ({ ...props }) => {
</View>
</View>
</View>
<Modal
visible={isModalVisible}
transparent
animationType="slide"
onRequestClose={() => setIsModalVisible(false)}
>
<TouchableOpacity
className="flex-1 bg-black/50"
activeOpacity={1}
onPress={() => setIsModalVisible(false)}
>
<View className="mt-auto bg-neutral-900 rounded-t-xl">
<View className="p-4 border-b border-neutral-800">
<Text className="text-lg font-bold text-center">
Select Language
</Text>
</View>
<View className="max-h-[50%]">
<TouchableOpacity
className="p-4 border-b border-neutral-800 flex-row items-center justify-between"
onPress={() => {
updateSettings({
defaultAudioLanguage: null,
});
setIsModalVisible(false);
}}
>
<Text>None</Text>
{!settings?.defaultAudioLanguage && (
<Ionicons name="checkmark" size={24} color="white" />
)}
</TouchableOpacity>
{cultures?.map((l) => (
<TouchableOpacity
key={l?.ThreeLetterISOLanguageName ?? "unknown"}
className="p-4 border-b border-neutral-800 flex-row items-center justify-between"
onPress={() => {
updateSettings({
defaultAudioLanguage: l,
});
setIsModalVisible(false);
}}
>
<Text>{l.DisplayName}</Text>
{settings?.defaultAudioLanguage
?.ThreeLetterISOLanguageName ===
l.ThreeLetterISOLanguageName && (
<Ionicons name="checkmark" size={24} color="white" />
)}
</TouchableOpacity>
))}
</View>
<TouchableOpacity
className="p-4 border-t border-neutral-800"
onPress={() => setIsModalVisible(false)}
>
<Text className="text-center text-purple-400">Cancel</Text>
</TouchableOpacity>
</View>
</TouchableOpacity>
</Modal>
</View>
);
};

View File

@@ -1,17 +1,18 @@
import { apiAtom, userAtom } from "@/providers/JellyfinProvider";
import { useSettings } from "@/utils/atoms/settings";
import { Ionicons } from "@expo/vector-icons";
import { getItemsApi } from "@jellyfin/sdk/lib/utils/api";
import { useQuery, useQueryClient } from "@tanstack/react-query";
import { useAtom } from "jotai";
import React, { useState } from "react";
import {
Linking,
Modal,
Switch,
TouchableOpacity,
View,
ViewProps,
} from "react-native";
import * as DropdownMenu from "zeego/dropdown-menu";
import { Button } from "../Button";
import { Input } from "../common/Input";
import { Text } from "../common/Text";
@@ -21,7 +22,6 @@ import { JellyseerrSettings } from "./Jellyseerr";
import { MediaProvider } from "./MediaContext";
import { MediaToggles } from "./MediaToggles";
import { SubtitleToggles } from "./SubtitleToggles";
interface Props extends ViewProps {}
export const SettingToggles: React.FC<Props> = ({ ...props }) => {
@@ -31,6 +31,8 @@ export const SettingToggles: React.FC<Props> = ({ ...props }) => {
const [user] = useAtom(userAtom);
const [marlinUrl, setMarlinUrl] = useState<string>("");
const queryClient = useQueryClient();
const [isSearchEngineModalVisible, setIsSearchEngineModalVisible] =
useState(false);
const {
data: mediaListCollections,
@@ -54,6 +56,13 @@ export const SettingToggles: React.FC<Props> = ({ ...props }) => {
staleTime: 0,
});
type SearchEngine = "Jellyfin" | "Marlin";
const searchEngines: Array<{ id: SearchEngine; name: string }> = [
{ id: "Jellyfin", name: "Jellyfin" },
{ id: "Marlin", name: "Marlin" },
];
if (!settings) return null;
return (
@@ -183,54 +192,27 @@ export const SettingToggles: React.FC<Props> = ({ ...props }) => {
</View>
<View className="flex flex-col">
<View
className={`
flex flex-row items-center space-x-2 justify-between bg-neutral-900 p-4
`}
>
<View className="flex flex-row items-center space-x-2 justify-between bg-neutral-900 p-4">
<View className="flex flex-col shrink">
<Text className="font-semibold">Search engine</Text>
<Text className="text-xs opacity-50">
Choose the search engine you want to use.
</Text>
</View>
<DropdownMenu.Root>
<DropdownMenu.Trigger>
<TouchableOpacity className="bg-neutral-800 rounded-lg border-neutral-900 border px-3 py-2 flex flex-row items-center justify-between">
<Text>{settings.searchEngine}</Text>
</TouchableOpacity>
</DropdownMenu.Trigger>
<DropdownMenu.Content
loop={true}
side="bottom"
align="start"
alignOffset={0}
avoidCollisions={true}
collisionPadding={8}
sideOffset={8}
>
<DropdownMenu.Label>Profiles</DropdownMenu.Label>
<DropdownMenu.Item
key="1"
onSelect={() => {
updateSettings({ searchEngine: "Jellyfin" });
queryClient.invalidateQueries({ queryKey: ["search"] });
}}
>
<DropdownMenu.ItemTitle>Jellyfin</DropdownMenu.ItemTitle>
</DropdownMenu.Item>
<DropdownMenu.Item
key="2"
onSelect={() => {
updateSettings({ searchEngine: "Marlin" });
queryClient.invalidateQueries({ queryKey: ["search"] });
}}
>
<DropdownMenu.ItemTitle>Marlin</DropdownMenu.ItemTitle>
</DropdownMenu.Item>
</DropdownMenu.Content>
</DropdownMenu.Root>
<TouchableOpacity
className="bg-neutral-800 rounded-lg border-neutral-900 border px-3 py-2 flex flex-row items-center justify-between"
onPress={() => setIsSearchEngineModalVisible(true)}
>
<Text>{settings.searchEngine}</Text>
<Ionicons
name="chevron-down"
size={16}
color="white"
style={{ opacity: 0.5, marginLeft: 8 }}
/>
</TouchableOpacity>
</View>
{settings.searchEngine === "Marlin" && (
<View className="flex flex-col bg-neutral-900 px-4 pb-4">
<View className="flex flex-row items-center space-x-2">
@@ -269,6 +251,55 @@ export const SettingToggles: React.FC<Props> = ({ ...props }) => {
</View>
)}
</View>
<Modal
visible={isSearchEngineModalVisible}
transparent
animationType="slide"
onRequestClose={() => setIsSearchEngineModalVisible(false)}
>
<TouchableOpacity
className="flex-1 bg-black/50"
activeOpacity={1}
onPress={() => setIsSearchEngineModalVisible(false)}
>
<View className="mt-auto bg-neutral-900 rounded-t-xl">
<View className="p-4 border-b border-neutral-800">
<Text className="text-lg font-bold text-center">
Select Search Engine
</Text>
</View>
<View className="max-h-[50%]">
{searchEngines.map((engine) => (
<TouchableOpacity
key={engine.id}
className="p-4 border-b border-neutral-800 flex-row items-center justify-between"
onPress={() => {
updateSettings({
searchEngine: engine.id,
});
queryClient.invalidateQueries({ queryKey: ["search"] });
setIsSearchEngineModalVisible(false);
}}
>
<Text>{engine.name}</Text>
{settings.searchEngine === engine.id && (
<Ionicons name="checkmark" size={24} color="white" />
)}
</TouchableOpacity>
))}
</View>
<TouchableOpacity
className="p-4 border-t border-neutral-800"
onPress={() => setIsSearchEngineModalVisible(false)}
>
<Text className="text-center text-purple-400">Cancel</Text>
</TouchableOpacity>
</View>
</TouchableOpacity>
</Modal>
</View>
</View>
<JellyseerrSettings />

View File

@@ -1,9 +1,10 @@
import { TouchableOpacity, View, ViewProps } from "react-native";
import * as DropdownMenu from "zeego/dropdown-menu";
import { Ionicons } from "@expo/vector-icons";
import { SubtitlePlaybackMode } from "@jellyfin/sdk/lib/generated-client";
import { useState } from "react";
import { Modal, TouchableOpacity, View, ViewProps } from "react-native";
import { Switch } from "react-native-gesture-handler";
import { Text } from "../common/Text";
import { useMedia } from "./MediaContext";
import { Switch } from "react-native-gesture-handler";
import { SubtitlePlaybackMode } from "@jellyfin/sdk/lib/generated-client";
interface Props extends ViewProps {}
@@ -11,6 +12,9 @@ export const SubtitleToggles: React.FC<Props> = ({ ...props }) => {
const media = useMedia();
const { settings, updateSettings } = media;
const cultures = media.cultures;
const [isLanguageModalVisible, setIsLanguageModalVisible] = useState(false);
const [isModeModalVisible, setIsModeModalVisible] = useState(false);
if (!settings) return null;
const subtitleModes = [
@@ -24,69 +28,31 @@ export const SubtitleToggles: React.FC<Props> = ({ ...props }) => {
return (
<View>
<Text className="text-lg font-bold mb-2">Subtitle</Text>
<View className="flex flex-col rounded-xl mb-4 overflow-hidden divide-y-2 divide-solid divide-neutral-800">
<View
className={`
flex flex-row items-center space-x-2 justify-between bg-neutral-900 p-4
`}
>
<View className="flex flex-col rounded-xl mb-4 overflow-hidden divide-y-2 divide-solid divide-neutral-800">
<View className="flex flex-row items-center space-x-2 justify-between bg-neutral-900 p-4">
<View className="flex flex-col shrink">
<Text className="font-semibold">Subtitle language</Text>
<Text className="text-xs opacity-50">
Choose a default subtitle language.
</Text>
</View>
<DropdownMenu.Root>
<DropdownMenu.Trigger>
<TouchableOpacity className="bg-neutral-800 rounded-lg border-neutral-900 border px-3 py-2 flex flex-row items-center justify-between">
<Text>
{settings?.defaultSubtitleLanguage?.DisplayName || "None"}
</Text>
</TouchableOpacity>
</DropdownMenu.Trigger>
<DropdownMenu.Content
loop={true}
side="bottom"
align="start"
alignOffset={0}
avoidCollisions={true}
collisionPadding={8}
sideOffset={8}
>
<DropdownMenu.Label>Languages</DropdownMenu.Label>
<DropdownMenu.Item
key={"none-subs"}
onSelect={() => {
updateSettings({
defaultSubtitleLanguage: null,
});
}}
>
<DropdownMenu.ItemTitle>None</DropdownMenu.ItemTitle>
</DropdownMenu.Item>
{cultures?.map((l) => (
<DropdownMenu.Item
key={l?.ThreeLetterISOLanguageName ?? "unknown"}
onSelect={() => {
updateSettings({
defaultSubtitleLanguage: l,
});
}}
>
<DropdownMenu.ItemTitle>
{l.DisplayName}
</DropdownMenu.ItemTitle>
</DropdownMenu.Item>
))}
</DropdownMenu.Content>
</DropdownMenu.Root>
<TouchableOpacity
className="bg-neutral-800 rounded-lg border-neutral-900 border px-3 py-2 flex flex-row items-center justify-between"
onPress={() => setIsLanguageModalVisible(true)}
>
<Text>
{settings?.defaultSubtitleLanguage?.DisplayName || "None"}
</Text>
<Ionicons
name="chevron-down"
size={16}
color="white"
style={{ opacity: 0.5, marginLeft: 8 }}
/>
</TouchableOpacity>
</View>
<View
className={`
flex flex-row items-center space-x-2 justify-between bg-neutral-900 p-4
`}
>
<View className="flex flex-row items-center space-x-2 justify-between bg-neutral-900 p-4">
<View className="flex flex-col shrink">
<Text className="font-semibold">Subtitle Mode</Text>
<Text className="text-xs opacity-50 mr-2">
@@ -95,36 +61,18 @@ export const SubtitleToggles: React.FC<Props> = ({ ...props }) => {
multiple options are available.
</Text>
</View>
<DropdownMenu.Root>
<DropdownMenu.Trigger>
<TouchableOpacity className="bg-neutral-800 rounded-lg border-neutral-900 border px-3 py-2 flex flex-row items-center justify-between">
<Text>{settings?.subtitleMode || "Loading"}</Text>
</TouchableOpacity>
</DropdownMenu.Trigger>
<DropdownMenu.Content
loop={true}
side="bottom"
align="start"
alignOffset={0}
avoidCollisions={true}
collisionPadding={8}
sideOffset={8}
>
<DropdownMenu.Label>Subtitle Mode</DropdownMenu.Label>
{subtitleModes?.map((l) => (
<DropdownMenu.Item
key={l}
onSelect={() => {
updateSettings({
subtitleMode: l,
});
}}
>
<DropdownMenu.ItemTitle>{l}</DropdownMenu.ItemTitle>
</DropdownMenu.Item>
))}
</DropdownMenu.Content>
</DropdownMenu.Root>
<TouchableOpacity
className="bg-neutral-800 rounded-lg border-neutral-900 border px-3 py-2 flex flex-row items-center justify-between"
onPress={() => setIsModeModalVisible(true)}
>
<Text>{settings?.subtitleMode || "Loading"}</Text>
<Ionicons
name="chevron-down"
size={16}
color="white"
style={{ opacity: 0.5, marginLeft: 8 }}
/>
</TouchableOpacity>
</View>
<View className="flex flex-col">
@@ -186,6 +134,119 @@ export const SubtitleToggles: React.FC<Props> = ({ ...props }) => {
</View>
</View>
</View>
<Modal
visible={isLanguageModalVisible}
transparent
animationType="slide"
onRequestClose={() => setIsLanguageModalVisible(false)}
>
<TouchableOpacity
className="flex-1 bg-black/50"
activeOpacity={1}
onPress={() => setIsLanguageModalVisible(false)}
>
<View className="mt-auto bg-neutral-900 rounded-t-xl">
<View className="p-4 border-b border-neutral-800">
<Text className="text-lg font-bold text-center">
Select Language
</Text>
</View>
<View className="max-h-[50%]">
<TouchableOpacity
className="p-4 border-b border-neutral-800 flex-row items-center justify-between"
onPress={() => {
updateSettings({
defaultSubtitleLanguage: null,
});
setIsLanguageModalVisible(false);
}}
>
<Text>None</Text>
{!settings?.defaultSubtitleLanguage && (
<Ionicons name="checkmark" size={24} color="white" />
)}
</TouchableOpacity>
{cultures?.map((l) => (
<TouchableOpacity
key={l?.ThreeLetterISOLanguageName ?? "unknown"}
className="p-4 border-b border-neutral-800 flex-row items-center justify-between"
onPress={() => {
updateSettings({
defaultSubtitleLanguage: l,
});
setIsLanguageModalVisible(false);
}}
>
<Text>{l.DisplayName}</Text>
{settings?.defaultSubtitleLanguage
?.ThreeLetterISOLanguageName ===
l.ThreeLetterISOLanguageName && (
<Ionicons name="checkmark" size={24} color="white" />
)}
</TouchableOpacity>
))}
</View>
<TouchableOpacity
className="p-4 border-t border-neutral-800"
onPress={() => setIsLanguageModalVisible(false)}
>
<Text className="text-center text-purple-400">Cancel</Text>
</TouchableOpacity>
</View>
</TouchableOpacity>
</Modal>
{/* Subtitle Mode Selection Modal */}
<Modal
visible={isModeModalVisible}
transparent
animationType="slide"
onRequestClose={() => setIsModeModalVisible(false)}
>
<TouchableOpacity
className="flex-1 bg-black/50"
activeOpacity={1}
onPress={() => setIsModeModalVisible(false)}
>
<View className="mt-auto bg-neutral-900 rounded-t-xl">
<View className="p-4 border-b border-neutral-800">
<Text className="text-lg font-bold text-center">
Select Subtitle Mode
</Text>
</View>
<View className="max-h-[50%]">
{subtitleModes?.map((mode) => (
<TouchableOpacity
key={mode}
className="p-4 border-b border-neutral-800 flex-row items-center justify-between"
onPress={() => {
updateSettings({
subtitleMode: mode,
});
setIsModeModalVisible(false);
}}
>
<Text>{mode}</Text>
{settings?.subtitleMode === mode && (
<Ionicons name="checkmark" size={24} color="white" />
)}
</TouchableOpacity>
))}
</View>
<TouchableOpacity
className="p-4 border-t border-neutral-800"
onPress={() => setIsModeModalVisible(false)}
>
<Text className="text-center text-purple-400">Cancel</Text>
</TouchableOpacity>
</View>
</TouchableOpacity>
</Modal>
</View>
);
};