mirror of
https://github.com/streamyfin/streamyfin.git
synced 2026-01-15 23:59:08 +00:00
fix: refactor
This commit is contained in:
@@ -1,17 +1,15 @@
|
||||
import { Chromecast } from "@/components/Chromecast";
|
||||
import { Text } from "@/components/common/Text";
|
||||
import { DownloadItem } from "@/components/DownloadItem";
|
||||
import { PlayedStatus } from "@/components/PlayedStatus";
|
||||
import { CastAndCrew } from "@/components/series/CastAndCrew";
|
||||
import { CurrentSeries } from "@/components/series/CurrentSeries";
|
||||
import { SimilarItems } from "@/components/SimilarItems";
|
||||
import { VideoPlayer } from "@/components/VideoPlayer";
|
||||
import { apiAtom, userAtom } from "@/providers/JellyfinProvider";
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
import { Image } from "expo-image";
|
||||
import { router, useLocalSearchParams } from "expo-router";
|
||||
import { useAtom } from "jotai";
|
||||
import { useCallback, useEffect, useMemo, useState } from "react";
|
||||
import { useCallback, useMemo, useState } from "react";
|
||||
import {
|
||||
ActivityIndicator,
|
||||
ScrollView,
|
||||
@@ -36,10 +34,13 @@ import ios12 from "@/utils/profiles/ios12";
|
||||
import { currentlyPlayingItemAtom } from "@/components/CurrentlyPlayingBar";
|
||||
import { AudioTrackSelector } from "@/components/AudioTrackSelector";
|
||||
import { SubtitleTrackSelector } from "@/components/SubtitleTrackSelector";
|
||||
import { BaseItemDto } from "@jellyfin/sdk/lib/generated-client/models";
|
||||
import { Button } from "@/components/Button";
|
||||
import { Ionicons } from "@expo/vector-icons";
|
||||
import { NextEpisodeButton } from "@/components/series/NextEpisodeButton";
|
||||
import { Badge } from "@/components/Badge";
|
||||
import { FontAwesome, Ionicons } from "@expo/vector-icons";
|
||||
import { Ratings } from "@/components/Ratings";
|
||||
import { SeriesTitleHeader } from "@/components/series/SeriesTitleHeader";
|
||||
import { MoviesTitleHeader } from "@/components/movies/MoviesTitleHeader";
|
||||
import { OverviewText } from "@/components/OverviewText";
|
||||
|
||||
const page: React.FC = () => {
|
||||
const local = useLocalSearchParams();
|
||||
@@ -134,7 +135,7 @@ const page: React.FC = () => {
|
||||
staleTime: 0,
|
||||
});
|
||||
|
||||
const [cp, setCp] = useAtom(currentlyPlayingItemAtom);
|
||||
const [, setCp] = useAtom(currentlyPlayingItemAtom);
|
||||
const client = useRemoteMediaClient();
|
||||
|
||||
const onPressPlay = useCallback(
|
||||
@@ -212,50 +213,14 @@ const page: React.FC = () => {
|
||||
<View className="flex flex-col px-4 pt-4">
|
||||
<View className="flex flex-col">
|
||||
{item.Type === "Episode" ? (
|
||||
<>
|
||||
<TouchableOpacity
|
||||
onPress={() =>
|
||||
router.push(`/(auth)/series/${item.SeriesId}/page`)
|
||||
}
|
||||
>
|
||||
<Text className="text-center opacity-50">
|
||||
{item?.SeriesName}
|
||||
</Text>
|
||||
</TouchableOpacity>
|
||||
<View className="flex flex-row items-center self-center px-4">
|
||||
<Text className="text-center font-bold text-2xl mr-2">
|
||||
{item?.Name}
|
||||
</Text>
|
||||
</View>
|
||||
<View>
|
||||
<View className="flex flex-row items-center self-center">
|
||||
<TouchableOpacity onPress={() => {}}>
|
||||
<Text className="text-center opacity-50">
|
||||
{item?.SeasonName}
|
||||
</Text>
|
||||
</TouchableOpacity>
|
||||
<Text className="text-center opacity-50 mx-2">{"—"}</Text>
|
||||
<Text className="text-center opacity-50">
|
||||
{`Episode ${item.IndexNumber}`}
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
<Text className="text-center opacity-50">
|
||||
{item.ProductionYear}
|
||||
</Text>
|
||||
</>
|
||||
<SeriesTitleHeader item={item} />
|
||||
) : (
|
||||
<>
|
||||
<View className="flex flex-row items-center self-center px-4">
|
||||
<Text className="text-center font-bold text-2xl mr-2">
|
||||
{item?.Name}
|
||||
</Text>
|
||||
</View>
|
||||
<Text className="text-center opacity-50">
|
||||
{item?.ProductionYear}
|
||||
</Text>
|
||||
<MoviesTitleHeader item={item} />
|
||||
</>
|
||||
)}
|
||||
<Text className="text-center opacity-50">{item?.ProductionYear}</Text>
|
||||
<Ratings item={item} />
|
||||
</View>
|
||||
|
||||
<View className="flex flex-row justify-between items-center w-full my-4">
|
||||
@@ -266,7 +231,8 @@ const page: React.FC = () => {
|
||||
)}
|
||||
<PlayedStatus item={item} />
|
||||
</View>
|
||||
<Text>{item.Overview}</Text>
|
||||
|
||||
<OverviewText text={item.Overview} />
|
||||
</View>
|
||||
<View className="flex flex-col p-4 w-full">
|
||||
<View className="flex flex-row items-center space-x-2 w-full">
|
||||
|
||||
36
components/Badge.tsx
Normal file
36
components/Badge.tsx
Normal file
@@ -0,0 +1,36 @@
|
||||
import { View, ViewProps } from "react-native";
|
||||
import { Text } from "./common/Text";
|
||||
|
||||
interface Props extends ViewProps {
|
||||
text?: string | number | null;
|
||||
variant?: "gray" | "purple";
|
||||
iconLeft?: React.ReactNode;
|
||||
}
|
||||
|
||||
export const Badge: React.FC<Props> = ({
|
||||
iconLeft,
|
||||
text,
|
||||
variant = "purple",
|
||||
...props
|
||||
}) => {
|
||||
return (
|
||||
<View
|
||||
{...props}
|
||||
className={`
|
||||
rounded p-1 shrink grow-0 self-start flex flex-row items-center px-1.5
|
||||
${variant === "purple" && "bg-purple-600"}
|
||||
${variant === "gray" && "bg-neutral-800"}
|
||||
`}
|
||||
>
|
||||
{iconLeft && <View className="mr-1">{iconLeft}</View>}
|
||||
<Text
|
||||
className={`
|
||||
text-xs
|
||||
${variant === "purple" && "text-white"}
|
||||
`}
|
||||
>
|
||||
{text}
|
||||
</Text>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
38
components/OverviewText.tsx
Normal file
38
components/OverviewText.tsx
Normal file
@@ -0,0 +1,38 @@
|
||||
import { TouchableOpacity, View, ViewProps } from "react-native";
|
||||
import { Text } from "@/components/common/Text";
|
||||
import { tc } from "@/utils/textTools";
|
||||
import { useState } from "react";
|
||||
|
||||
interface Props extends ViewProps {
|
||||
text?: string | null;
|
||||
}
|
||||
|
||||
const LIMIT = 150;
|
||||
|
||||
export const OverviewText: React.FC<Props> = ({ text, ...props }) => {
|
||||
const [limit, setLimit] = useState(LIMIT);
|
||||
|
||||
if (!text) return null;
|
||||
|
||||
if (text.length > LIMIT)
|
||||
return (
|
||||
<TouchableOpacity
|
||||
onPress={() =>
|
||||
setLimit((prev) => (prev === LIMIT ? text.length : LIMIT))
|
||||
}
|
||||
>
|
||||
<View {...props} className="">
|
||||
<Text>{tc(text, limit)}</Text>
|
||||
<Text className="text-purple-600 mt-1">
|
||||
{limit === LIMIT ? "Show more" : "Show less"}
|
||||
</Text>
|
||||
</View>
|
||||
</TouchableOpacity>
|
||||
);
|
||||
|
||||
return (
|
||||
<View {...props}>
|
||||
<Text>{text}</Text>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
12
components/_template.tsx
Normal file
12
components/_template.tsx
Normal file
@@ -0,0 +1,12 @@
|
||||
import { View, ViewProps } from "react-native";
|
||||
import { Text } from "@/components/common/Text";
|
||||
|
||||
interface Props extends ViewProps {}
|
||||
|
||||
export const TitleHeader: React.FC<Props> = ({ ...props }) => {
|
||||
return (
|
||||
<View {...props}>
|
||||
<Text></Text>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
21
components/movies/MoviesTitleHeader.tsx
Normal file
21
components/movies/MoviesTitleHeader.tsx
Normal file
@@ -0,0 +1,21 @@
|
||||
import { TouchableOpacity, View, ViewProps } from "react-native";
|
||||
import { Text } from "@/components/common/Text";
|
||||
import { useRouter } from "expo-router";
|
||||
import { BaseItemDto } from "@jellyfin/sdk/lib/generated-client/models";
|
||||
|
||||
interface Props extends ViewProps {
|
||||
item: BaseItemDto;
|
||||
}
|
||||
|
||||
export const MoviesTitleHeader: React.FC<Props> = ({ item, ...props }) => {
|
||||
const router = useRouter();
|
||||
return (
|
||||
<>
|
||||
<View className="flex flex-row items-center self-center px-4">
|
||||
<Text className="text-center font-bold text-2xl mr-2">
|
||||
{item?.Name}
|
||||
</Text>
|
||||
</View>
|
||||
</>
|
||||
);
|
||||
};
|
||||
37
components/series/SeriesTitleHeader.tsx
Normal file
37
components/series/SeriesTitleHeader.tsx
Normal file
@@ -0,0 +1,37 @@
|
||||
import { TouchableOpacity, View, ViewProps } from "react-native";
|
||||
import { Text } from "@/components/common/Text";
|
||||
import { useRouter } from "expo-router";
|
||||
import { BaseItemDto } from "@jellyfin/sdk/lib/generated-client/models";
|
||||
|
||||
interface Props extends ViewProps {
|
||||
item: BaseItemDto;
|
||||
}
|
||||
|
||||
export const SeriesTitleHeader: React.FC<Props> = ({ item, ...props }) => {
|
||||
const router = useRouter();
|
||||
return (
|
||||
<>
|
||||
<TouchableOpacity
|
||||
onPress={() => router.push(`/(auth)/series/${item.SeriesId}/page`)}
|
||||
>
|
||||
<Text className="text-center opacity-50">{item?.SeriesName}</Text>
|
||||
</TouchableOpacity>
|
||||
<View className="flex flex-row items-center self-center px-4">
|
||||
<Text className="text-center font-bold text-2xl mr-2">
|
||||
{item?.Name}
|
||||
</Text>
|
||||
</View>
|
||||
<View>
|
||||
<View className="flex flex-row items-center self-center">
|
||||
<TouchableOpacity onPress={() => {}}>
|
||||
<Text className="text-center opacity-50">{item?.SeasonName}</Text>
|
||||
</TouchableOpacity>
|
||||
<Text className="text-center opacity-50 mx-2">{"—"}</Text>
|
||||
<Text className="text-center opacity-50">
|
||||
{`Episode ${item.IndexNumber}`}
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
</>
|
||||
);
|
||||
};
|
||||
Reference in New Issue
Block a user