mirror of
https://github.com/streamyfin/streamyfin.git
synced 2026-06-04 21:18:31 +01:00
fix: refactor
This commit is contained in:
@@ -210,8 +210,6 @@ export default function index() {
|
|||||||
limit: 10,
|
limit: 10,
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log("Popular", response.data.Items?.length);
|
|
||||||
|
|
||||||
return response.data.Items || [];
|
return response.data.Items || [];
|
||||||
},
|
},
|
||||||
enabled: !!api && !!user?.Id && !!mediaListCollection,
|
enabled: !!api && !!user?.Id && !!mediaListCollection,
|
||||||
|
|||||||
@@ -60,8 +60,6 @@ const page: React.FC = () => {
|
|||||||
const sortBy: ItemSortBy[] = [];
|
const sortBy: ItemSortBy[] = [];
|
||||||
const includeItemTypes: BaseItemKind[] = [];
|
const includeItemTypes: BaseItemKind[] = [];
|
||||||
|
|
||||||
console.log("Collection", { collection });
|
|
||||||
|
|
||||||
switch (collection?.CollectionType) {
|
switch (collection?.CollectionType) {
|
||||||
case "movies":
|
case "movies":
|
||||||
sortBy.push("SortName", "ProductionYear");
|
sortBy.push("SortName", "ProductionYear");
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import { AudioTrackSelector } from "@/components/AudioTrackSelector";
|
|||||||
import { Bitrate, BitrateSelector } from "@/components/BitrateSelector";
|
import { Bitrate, BitrateSelector } from "@/components/BitrateSelector";
|
||||||
import {
|
import {
|
||||||
currentlyPlayingItemAtom,
|
currentlyPlayingItemAtom,
|
||||||
|
fullScreenAtom,
|
||||||
playingAtom,
|
playingAtom,
|
||||||
} from "@/components/CurrentlyPlayingBar";
|
} from "@/components/CurrentlyPlayingBar";
|
||||||
import { DownloadItem } from "@/components/DownloadItem";
|
import { DownloadItem } from "@/components/DownloadItem";
|
||||||
@@ -37,6 +38,10 @@ import CastContext, {
|
|||||||
useRemoteMediaClient,
|
useRemoteMediaClient,
|
||||||
} from "react-native-google-cast";
|
} from "react-native-google-cast";
|
||||||
import { ParallaxScrollView } from "../../../components/ParallaxPage";
|
import { ParallaxScrollView } from "../../../components/ParallaxPage";
|
||||||
|
import { useSettings } from "@/utils/atoms/settings";
|
||||||
|
import ios from "@/utils/profiles/ios";
|
||||||
|
import native from "@/utils/profiles/native";
|
||||||
|
import old from "@/utils/profiles/old";
|
||||||
|
|
||||||
const page: React.FC = () => {
|
const page: React.FC = () => {
|
||||||
const local = useLocalSearchParams();
|
const local = useLocalSearchParams();
|
||||||
@@ -45,10 +50,13 @@ const page: React.FC = () => {
|
|||||||
const [api] = useAtom(apiAtom);
|
const [api] = useAtom(apiAtom);
|
||||||
const [user] = useAtom(userAtom);
|
const [user] = useAtom(userAtom);
|
||||||
|
|
||||||
|
const [settings] = useSettings();
|
||||||
|
|
||||||
const castDevice = useCastDevice();
|
const castDevice = useCastDevice();
|
||||||
|
|
||||||
const [, setCurrentlyPlying] = useAtom(currentlyPlayingItemAtom);
|
const [, setCurrentlyPlying] = useAtom(currentlyPlayingItemAtom);
|
||||||
const [, setPlaying] = useAtom(playingAtom);
|
const [, setPlaying] = useAtom(playingAtom);
|
||||||
|
const [, setFullscreen] = useAtom(fullScreenAtom);
|
||||||
|
|
||||||
const client = useRemoteMediaClient();
|
const client = useRemoteMediaClient();
|
||||||
const chromecastReady = useMemo(() => !!castDevice?.deviceId, [castDevice]);
|
const chromecastReady = useMemo(() => !!castDevice?.deviceId, [castDevice]);
|
||||||
@@ -95,10 +103,21 @@ const page: React.FC = () => {
|
|||||||
castDevice,
|
castDevice,
|
||||||
selectedAudioStream,
|
selectedAudioStream,
|
||||||
selectedSubtitleStream,
|
selectedSubtitleStream,
|
||||||
|
settings,
|
||||||
],
|
],
|
||||||
queryFn: async () => {
|
queryFn: async () => {
|
||||||
if (!api || !user?.Id || !sessionData) return null;
|
if (!api || !user?.Id || !sessionData) return null;
|
||||||
|
|
||||||
|
let deviceProfile: any = ios;
|
||||||
|
|
||||||
|
if (castDevice?.deviceId) {
|
||||||
|
deviceProfile = chromecastProfile;
|
||||||
|
} else if (settings?.deviceProfile === "Native") {
|
||||||
|
deviceProfile = native;
|
||||||
|
} else if (settings?.deviceProfile === "Old") {
|
||||||
|
deviceProfile = old;
|
||||||
|
}
|
||||||
|
|
||||||
const url = await getStreamUrl({
|
const url = await getStreamUrl({
|
||||||
api,
|
api,
|
||||||
userId: user.Id,
|
userId: user.Id,
|
||||||
@@ -106,16 +125,17 @@ const page: React.FC = () => {
|
|||||||
startTimeTicks: item?.UserData?.PlaybackPositionTicks || 0,
|
startTimeTicks: item?.UserData?.PlaybackPositionTicks || 0,
|
||||||
maxStreamingBitrate: maxBitrate.value,
|
maxStreamingBitrate: maxBitrate.value,
|
||||||
sessionData,
|
sessionData,
|
||||||
deviceProfile: castDevice?.deviceId ? chromecastProfile : ios12,
|
deviceProfile,
|
||||||
audioStreamIndex: selectedAudioStream,
|
audioStreamIndex: selectedAudioStream,
|
||||||
subtitleStreamIndex: selectedSubtitleStream,
|
subtitleStreamIndex: selectedSubtitleStream,
|
||||||
|
forceDirectPlay: settings?.forceDirectPlay,
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log("Transcode URL: ", url);
|
console.log("Transcode URL: ", url);
|
||||||
|
|
||||||
return url;
|
return url;
|
||||||
},
|
},
|
||||||
enabled: !!sessionData,
|
enabled: !!sessionData && !!api && !!user?.Id && !!item?.Id,
|
||||||
staleTime: 0,
|
staleTime: 0,
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -147,11 +167,13 @@ const page: React.FC = () => {
|
|||||||
item,
|
item,
|
||||||
playbackUrl,
|
playbackUrl,
|
||||||
});
|
});
|
||||||
|
|
||||||
setPlaying(true);
|
setPlaying(true);
|
||||||
|
if (settings?.openFullScreenVideoPlayerByDefault === true) {
|
||||||
|
setFullscreen(true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[playbackUrl, item],
|
[playbackUrl, item, settings],
|
||||||
);
|
);
|
||||||
|
|
||||||
const backdropUrl = useMemo(
|
const backdropUrl = useMemo(
|
||||||
|
|||||||
@@ -20,12 +20,6 @@ const page: React.FC = () => {
|
|||||||
seasonIndex: string;
|
seasonIndex: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (seriesId) {
|
|
||||||
console.log("seasonIndex", seasonIndex);
|
|
||||||
}
|
|
||||||
}, [seriesId]);
|
|
||||||
|
|
||||||
const [api] = useAtom(apiAtom);
|
const [api] = useAtom(apiAtom);
|
||||||
const [user] = useAtom(userAtom);
|
const [user] = useAtom(userAtom);
|
||||||
|
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ import CastContext, {
|
|||||||
import { chromecastProfile } from "@/utils/profiles/chromecast";
|
import { chromecastProfile } from "@/utils/profiles/chromecast";
|
||||||
import {
|
import {
|
||||||
currentlyPlayingItemAtom,
|
currentlyPlayingItemAtom,
|
||||||
triggerPlayAtom,
|
playingAtom,
|
||||||
} from "@/components/CurrentlyPlayingBar";
|
} from "@/components/CurrentlyPlayingBar";
|
||||||
import { AudioTrackSelector } from "@/components/AudioTrackSelector";
|
import { AudioTrackSelector } from "@/components/AudioTrackSelector";
|
||||||
import { SubtitleTrackSelector } from "@/components/SubtitleTrackSelector";
|
import { SubtitleTrackSelector } from "@/components/SubtitleTrackSelector";
|
||||||
@@ -40,6 +40,8 @@ const page: React.FC = () => {
|
|||||||
const [api] = useAtom(apiAtom);
|
const [api] = useAtom(apiAtom);
|
||||||
const [user] = useAtom(userAtom);
|
const [user] = useAtom(userAtom);
|
||||||
|
|
||||||
|
const [, setPlaying] = useAtom(playingAtom);
|
||||||
|
|
||||||
const castDevice = useCastDevice();
|
const castDevice = useCastDevice();
|
||||||
const navigation = useNavigation();
|
const navigation = useNavigation();
|
||||||
|
|
||||||
@@ -139,7 +141,6 @@ const page: React.FC = () => {
|
|||||||
|
|
||||||
const [, setCp] = useAtom(currentlyPlayingItemAtom);
|
const [, setCp] = useAtom(currentlyPlayingItemAtom);
|
||||||
const client = useRemoteMediaClient();
|
const client = useRemoteMediaClient();
|
||||||
const [, setPlayTrigger] = useAtom(triggerPlayAtom);
|
|
||||||
|
|
||||||
const onPressPlay = useCallback(
|
const onPressPlay = useCallback(
|
||||||
async (type: "device" | "cast" = "device") => {
|
async (type: "device" | "cast" = "device") => {
|
||||||
@@ -169,9 +170,7 @@ const page: React.FC = () => {
|
|||||||
item,
|
item,
|
||||||
playbackUrl,
|
playbackUrl,
|
||||||
});
|
});
|
||||||
|
setPlaying(true);
|
||||||
// Use this trigger to initiate playback in another component (CurrentlyPlayingBar)
|
|
||||||
setPlayTrigger((prev) => prev + 1);
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[playbackUrl, item],
|
[playbackUrl, item],
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ import { atom, useAtom } from "jotai";
|
|||||||
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
||||||
import {
|
import {
|
||||||
ActivityIndicator,
|
ActivityIndicator,
|
||||||
|
Alert,
|
||||||
Platform,
|
Platform,
|
||||||
TouchableOpacity,
|
TouchableOpacity,
|
||||||
View,
|
View,
|
||||||
@@ -33,14 +34,12 @@ export const currentlyPlayingItemAtom = atom<{
|
|||||||
playbackUrl: string;
|
playbackUrl: string;
|
||||||
} | null>(null);
|
} | null>(null);
|
||||||
|
|
||||||
export const triggerPlayAtom = atom(0);
|
|
||||||
|
|
||||||
export const playingAtom = atom(false);
|
export const playingAtom = atom(false);
|
||||||
|
export const fullScreenAtom = atom(false);
|
||||||
|
|
||||||
export const CurrentlyPlayingBar: React.FC = () => {
|
export const CurrentlyPlayingBar: React.FC = () => {
|
||||||
const queryClient = useQueryClient();
|
const queryClient = useQueryClient();
|
||||||
const segments = useSegments();
|
const segments = useSegments();
|
||||||
const [settings] = useSettings();
|
|
||||||
|
|
||||||
const [api] = useAtom(apiAtom);
|
const [api] = useAtom(apiAtom);
|
||||||
const [user] = useAtom(userAtom);
|
const [user] = useAtom(userAtom);
|
||||||
@@ -48,10 +47,10 @@ export const CurrentlyPlayingBar: React.FC = () => {
|
|||||||
const [currentlyPlaying, setCurrentlyPlaying] = useAtom(
|
const [currentlyPlaying, setCurrentlyPlaying] = useAtom(
|
||||||
currentlyPlayingItemAtom,
|
currentlyPlayingItemAtom,
|
||||||
);
|
);
|
||||||
|
const [fullScreen, setFullScreen] = useAtom(fullScreenAtom);
|
||||||
|
|
||||||
const videoRef = useRef<VideoRef | null>(null);
|
const videoRef = useRef<VideoRef | null>(null);
|
||||||
const [progress, setProgress] = useState(0);
|
const [progress, setProgress] = useState(0);
|
||||||
const [fullScreen, setFullScreen] = useState(false);
|
|
||||||
|
|
||||||
const aBottom = useSharedValue(0);
|
const aBottom = useSharedValue(0);
|
||||||
const aPadding = useSharedValue(0);
|
const aPadding = useSharedValue(0);
|
||||||
@@ -148,11 +147,13 @@ export const CurrentlyPlayingBar: React.FC = () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
if (!item || !api) return;
|
||||||
|
|
||||||
if (playing) {
|
if (playing) {
|
||||||
videoRef.current?.resume();
|
videoRef.current?.resume();
|
||||||
} else {
|
} else {
|
||||||
videoRef.current?.pause();
|
videoRef.current?.pause();
|
||||||
if (progress > 0 && sessionData?.PlaySessionId && api)
|
if (progress > 0 && sessionData?.PlaySessionId)
|
||||||
reportPlaybackStopped({
|
reportPlaybackStopped({
|
||||||
api,
|
api,
|
||||||
itemId: item?.Id,
|
itemId: item?.Id,
|
||||||
@@ -171,6 +172,15 @@ export const CurrentlyPlayingBar: React.FC = () => {
|
|||||||
}
|
}
|
||||||
}, [playing, progress, item, sessionData]);
|
}, [playing, progress, item, sessionData]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
console.log("Full screen changed", fullScreen);
|
||||||
|
if (fullScreen === true) {
|
||||||
|
videoRef.current?.presentFullscreenPlayer();
|
||||||
|
} else {
|
||||||
|
videoRef.current?.dismissFullscreenPlayer();
|
||||||
|
}
|
||||||
|
}, [fullScreen]);
|
||||||
|
|
||||||
const startPosition = useMemo(
|
const startPosition = useMemo(
|
||||||
() =>
|
() =>
|
||||||
item?.UserData?.PlaybackPositionTicks
|
item?.UserData?.PlaybackPositionTicks
|
||||||
@@ -276,6 +286,9 @@ export const CurrentlyPlayingBar: React.FC = () => {
|
|||||||
"ERROR",
|
"ERROR",
|
||||||
"Video playback error: " + JSON.stringify(e),
|
"Video playback error: " + JSON.stringify(e),
|
||||||
);
|
);
|
||||||
|
Alert.alert("Error", "Cannot play this video file.");
|
||||||
|
setPlaying(false);
|
||||||
|
setCurrentlyPlaying(null);
|
||||||
}}
|
}}
|
||||||
renderLoader={
|
renderLoader={
|
||||||
item?.Type !== "Audio" && (
|
item?.Type !== "Audio" && (
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ export const PlayButton: React.FC<Props> = ({
|
|||||||
onPress("device");
|
onPress("device");
|
||||||
break;
|
break;
|
||||||
case cancelButtonIndex:
|
case cancelButtonIndex:
|
||||||
console.log("calcel");
|
break;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -8,7 +8,12 @@ import { useAtom } from "jotai";
|
|||||||
|
|
||||||
import { Text } from "../common/Text";
|
import { Text } from "../common/Text";
|
||||||
import { useFiles } from "@/hooks/useFiles";
|
import { useFiles } from "@/hooks/useFiles";
|
||||||
import { currentlyPlayingItemAtom } from "../CurrentlyPlayingBar";
|
import {
|
||||||
|
currentlyPlayingItemAtom,
|
||||||
|
fullScreenAtom,
|
||||||
|
playingAtom,
|
||||||
|
} from "../CurrentlyPlayingBar";
|
||||||
|
import { useSettings } from "@/utils/atoms/settings";
|
||||||
|
|
||||||
interface EpisodeCardProps {
|
interface EpisodeCardProps {
|
||||||
item: BaseItemDto;
|
item: BaseItemDto;
|
||||||
@@ -22,16 +27,22 @@ interface EpisodeCardProps {
|
|||||||
export const EpisodeCard: React.FC<EpisodeCardProps> = ({ item }) => {
|
export const EpisodeCard: React.FC<EpisodeCardProps> = ({ item }) => {
|
||||||
const { deleteFile } = useFiles();
|
const { deleteFile } = useFiles();
|
||||||
const [, setCurrentlyPlaying] = useAtom(currentlyPlayingItemAtom);
|
const [, setCurrentlyPlaying] = useAtom(currentlyPlayingItemAtom);
|
||||||
|
const [, setPlaying] = useAtom(playingAtom);
|
||||||
|
const [, setFullscreen] = useAtom(fullScreenAtom);
|
||||||
|
const [settings] = useSettings();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles opening the file for playback.
|
* Handles opening the file for playback.
|
||||||
*/
|
*/
|
||||||
const handleOpenFile = useCallback(() => {
|
const handleOpenFile = useCallback(async () => {
|
||||||
setCurrentlyPlaying({
|
setCurrentlyPlaying({
|
||||||
item,
|
item,
|
||||||
playbackUrl: `${FileSystem.documentDirectory}/${item.Id}.mp4`,
|
playbackUrl: `${FileSystem.documentDirectory}/${item.Id}.mp4`,
|
||||||
});
|
});
|
||||||
}, [item, setCurrentlyPlaying]);
|
setPlaying(true);
|
||||||
|
if (settings?.openFullScreenVideoPlayerByDefault === true)
|
||||||
|
setFullscreen(true);
|
||||||
|
}, [item, setCurrentlyPlaying, settings]);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles deleting the file with haptic feedback.
|
* Handles deleting the file with haptic feedback.
|
||||||
|
|||||||
@@ -1,97 +1,99 @@
|
|||||||
|
import React, { useCallback } from "react";
|
||||||
import { TouchableOpacity, View } from "react-native";
|
import { TouchableOpacity, View } from "react-native";
|
||||||
import { Text } from "../common/Text";
|
|
||||||
import { BaseItemDto } from "@jellyfin/sdk/lib/generated-client/models";
|
import { BaseItemDto } from "@jellyfin/sdk/lib/generated-client/models";
|
||||||
import { runtimeTicksToMinutes } from "@/utils/time";
|
|
||||||
import * as ContextMenu from "zeego/context-menu";
|
import * as ContextMenu from "zeego/context-menu";
|
||||||
import { useFiles } from "@/hooks/useFiles";
|
|
||||||
import * as FileSystem from "expo-file-system";
|
import * as FileSystem from "expo-file-system";
|
||||||
import { useCallback } from "react";
|
|
||||||
import * as Haptics from "expo-haptics";
|
import * as Haptics from "expo-haptics";
|
||||||
import { useAtom } from "jotai";
|
import { useAtom } from "jotai";
|
||||||
import { currentlyPlayingItemAtom } from "../CurrentlyPlayingBar";
|
|
||||||
import { useQuery } from "@tanstack/react-query";
|
|
||||||
|
|
||||||
export const MovieCard: React.FC<{ item: BaseItemDto }> = ({ item }) => {
|
import { Text } from "../common/Text";
|
||||||
|
import { useFiles } from "@/hooks/useFiles";
|
||||||
|
import { runtimeTicksToMinutes } from "@/utils/time";
|
||||||
|
import {
|
||||||
|
currentlyPlayingItemAtom,
|
||||||
|
fullScreenAtom,
|
||||||
|
playingAtom,
|
||||||
|
} from "../CurrentlyPlayingBar";
|
||||||
|
import { useSettings } from "@/utils/atoms/settings";
|
||||||
|
|
||||||
|
interface MovieCardProps {
|
||||||
|
item: BaseItemDto;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MovieCard component displays a movie with context menu options.
|
||||||
|
* @param {MovieCardProps} props - The component props.
|
||||||
|
* @returns {React.ReactElement} The rendered MovieCard component.
|
||||||
|
*/
|
||||||
|
export const MovieCard: React.FC<MovieCardProps> = ({ item }) => {
|
||||||
const { deleteFile } = useFiles();
|
const { deleteFile } = useFiles();
|
||||||
const [_, setCp] = useAtom(currentlyPlayingItemAtom);
|
const [, setCurrentlyPlaying] = useAtom(currentlyPlayingItemAtom);
|
||||||
|
const [, setPlaying] = useAtom(playingAtom);
|
||||||
|
const [, setFullscreen] = useAtom(fullScreenAtom);
|
||||||
|
const [settings] = useSettings();
|
||||||
|
|
||||||
// const fetchFileSize = async () => {
|
/**
|
||||||
// const filePath = `${FileSystem.documentDirectory}/${item.Id}.mp4`;
|
* Handles opening the file for playback.
|
||||||
// const info = await FileSystem.getInfoAsync(filePath);
|
*/
|
||||||
// return info.exists ? info.size : null;
|
const handleOpenFile = useCallback(() => {
|
||||||
// };
|
console.log("Open movie file", item.Name);
|
||||||
|
setCurrentlyPlaying({
|
||||||
// const { data: fileSize } = useQuery({
|
|
||||||
// queryKey: ["fileSize", item?.Id],
|
|
||||||
// queryFn: fetchFileSize,
|
|
||||||
// });
|
|
||||||
|
|
||||||
const openFile = useCallback(() => {
|
|
||||||
setCp({
|
|
||||||
item,
|
item,
|
||||||
playbackUrl: `${FileSystem.documentDirectory}/${item.Id}.mp4`,
|
playbackUrl: `${FileSystem.documentDirectory}/${item.Id}.mp4`,
|
||||||
});
|
});
|
||||||
}, [item]);
|
setPlaying(true);
|
||||||
|
if (settings?.openFullScreenVideoPlayerByDefault === true) {
|
||||||
|
setFullscreen(true);
|
||||||
|
}
|
||||||
|
}, [item, setCurrentlyPlaying, setPlaying, settings]);
|
||||||
|
|
||||||
const options = [
|
/**
|
||||||
|
* Handles deleting the file with haptic feedback.
|
||||||
|
*/
|
||||||
|
const handleDeleteFile = useCallback(() => {
|
||||||
|
if (item.Id) {
|
||||||
|
deleteFile(item.Id);
|
||||||
|
Haptics.notificationAsync(Haptics.NotificationFeedbackType.Success);
|
||||||
|
}
|
||||||
|
}, [deleteFile, item.Id]);
|
||||||
|
|
||||||
|
const contextMenuOptions = [
|
||||||
{
|
{
|
||||||
label: "Delete",
|
label: "Delete",
|
||||||
onSelect: (id: string) => {
|
onSelect: handleDeleteFile,
|
||||||
deleteFile(id);
|
|
||||||
Haptics.notificationAsync(Haptics.NotificationFeedbackType.Success);
|
|
||||||
},
|
|
||||||
destructive: true,
|
destructive: true,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<ContextMenu.Root>
|
||||||
<ContextMenu.Root>
|
<ContextMenu.Trigger>
|
||||||
<ContextMenu.Trigger>
|
<TouchableOpacity
|
||||||
<TouchableOpacity
|
onPress={handleOpenFile}
|
||||||
onPress={openFile}
|
className="bg-neutral-900 border border-neutral-800 rounded-2xl p-4"
|
||||||
className="bg-neutral-900 border border-neutral-800 rounded-2xl p-4"
|
|
||||||
>
|
|
||||||
<Text className=" font-bold">{item.Name}</Text>
|
|
||||||
<View className="flex flex-col">
|
|
||||||
<Text className=" text-xs opacity-50">{item.ProductionYear}</Text>
|
|
||||||
<Text className=" text-xs opacity-50">
|
|
||||||
{runtimeTicksToMinutes(item.RunTimeTicks)}
|
|
||||||
</Text>
|
|
||||||
{/* <Text className=" text-xs opacity-50">
|
|
||||||
Size:{" "}
|
|
||||||
{fileSize
|
|
||||||
? `${(fileSize / 1000000).toFixed(0)} MB`
|
|
||||||
: "Calculating..."}{" "}
|
|
||||||
</Text>*/}
|
|
||||||
</View>
|
|
||||||
</TouchableOpacity>
|
|
||||||
</ContextMenu.Trigger>
|
|
||||||
<ContextMenu.Content
|
|
||||||
alignOffset={0}
|
|
||||||
avoidCollisions={false}
|
|
||||||
collisionPadding={0}
|
|
||||||
loop={false}
|
|
||||||
>
|
>
|
||||||
{options.map((i) => (
|
<Text className="font-bold">{item.Name}</Text>
|
||||||
<ContextMenu.Item
|
<View className="flex flex-col">
|
||||||
onSelect={() => {
|
<Text className="text-xs opacity-50">{item.ProductionYear}</Text>
|
||||||
i.onSelect(item.Id!);
|
<Text className="text-xs opacity-50">
|
||||||
}}
|
{runtimeTicksToMinutes(item.RunTimeTicks)}
|
||||||
key={i.label}
|
</Text>
|
||||||
destructive={i.destructive}
|
</View>
|
||||||
>
|
</TouchableOpacity>
|
||||||
<ContextMenu.ItemTitle
|
</ContextMenu.Trigger>
|
||||||
style={{
|
<ContextMenu.Content>
|
||||||
color: "red",
|
{contextMenuOptions.map((option) => (
|
||||||
}}
|
<ContextMenu.Item
|
||||||
>
|
key={option.label}
|
||||||
{i.label}
|
onSelect={option.onSelect}
|
||||||
</ContextMenu.ItemTitle>
|
destructive={option.destructive}
|
||||||
</ContextMenu.Item>
|
>
|
||||||
))}
|
<ContextMenu.ItemTitle style={{ color: "red" }}>
|
||||||
</ContextMenu.Content>
|
{option.label}
|
||||||
</ContextMenu.Root>
|
</ContextMenu.ItemTitle>
|
||||||
</>
|
</ContextMenu.Item>
|
||||||
|
))}
|
||||||
|
</ContextMenu.Content>
|
||||||
|
</ContextMenu.Root>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -19,10 +19,7 @@ import CastContext, {
|
|||||||
useCastDevice,
|
useCastDevice,
|
||||||
useRemoteMediaClient,
|
useRemoteMediaClient,
|
||||||
} from "react-native-google-cast";
|
} from "react-native-google-cast";
|
||||||
import {
|
import { currentlyPlayingItemAtom, playingAtom } from "../CurrentlyPlayingBar";
|
||||||
currentlyPlayingItemAtom,
|
|
||||||
triggerPlayAtom,
|
|
||||||
} from "../CurrentlyPlayingBar";
|
|
||||||
import { useActionSheet } from "@expo/react-native-action-sheet";
|
import { useActionSheet } from "@expo/react-native-action-sheet";
|
||||||
import ios from "@/utils/profiles/ios";
|
import ios from "@/utils/profiles/ios";
|
||||||
|
|
||||||
@@ -46,7 +43,7 @@ export const SongsListItem: React.FC<Props> = ({
|
|||||||
const [user] = useAtom(userAtom);
|
const [user] = useAtom(userAtom);
|
||||||
const castDevice = useCastDevice();
|
const castDevice = useCastDevice();
|
||||||
const [, setCp] = useAtom(currentlyPlayingItemAtom);
|
const [, setCp] = useAtom(currentlyPlayingItemAtom);
|
||||||
const [, setPlayTrigger] = useAtom(triggerPlayAtom);
|
const [, setPlaying] = useAtom(playingAtom);
|
||||||
|
|
||||||
const client = useRemoteMediaClient();
|
const client = useRemoteMediaClient();
|
||||||
const { showActionSheetWithOptions } = useActionSheet();
|
const { showActionSheetWithOptions } = useActionSheet();
|
||||||
@@ -74,7 +71,7 @@ export const SongsListItem: React.FC<Props> = ({
|
|||||||
play("device");
|
play("device");
|
||||||
break;
|
break;
|
||||||
case cancelButtonIndex:
|
case cancelButtonIndex:
|
||||||
console.log("calcel");
|
break;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
@@ -125,9 +122,7 @@ export const SongsListItem: React.FC<Props> = ({
|
|||||||
item,
|
item,
|
||||||
playbackUrl: url,
|
playbackUrl: url,
|
||||||
});
|
});
|
||||||
|
setPlaying(true);
|
||||||
// Use this trigger to initiate playback in another component (CurrentlyPlayingBar)
|
|
||||||
setPlayTrigger((prev) => prev + 1);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user