mirror of
https://github.com/movie-web/native-app.git
synced 2025-09-13 16:33:26 +00:00
add play and seek buttons
This commit is contained in:
@@ -13,6 +13,7 @@ import { fetchMediaDetails } from "@movie-web/tmdb";
|
||||
|
||||
import type { ItemData } from "~/components/item/item";
|
||||
import { Header } from "~/components/player/Header";
|
||||
import { MiddleControls } from "~/components/player/MiddleButtons";
|
||||
import { usePlayerStore } from "~/stores/player/store";
|
||||
|
||||
export default function VideoPlayerWrapper() {
|
||||
@@ -145,6 +146,7 @@ const VideoPlayer: React.FC<VideoPlayerProps> = ({ data }) => {
|
||||
/>
|
||||
{isLoading && <ActivityIndicator size="large" color="#0000ff" />}
|
||||
{!isLoading && data && <Header title={data.title} />}
|
||||
{!isLoading && <MiddleControls />}
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
@@ -1,13 +1,24 @@
|
||||
import { View } from "react-native";
|
||||
import React from "react";
|
||||
import { TouchableOpacity } from "react-native";
|
||||
|
||||
import { usePlayerStore } from "~/stores/player/store";
|
||||
|
||||
interface ControlsProps {
|
||||
interface ControlsProps extends React.ComponentProps<typeof TouchableOpacity> {
|
||||
children: React.ReactNode;
|
||||
}
|
||||
|
||||
export const Controls = ({ children }: ControlsProps) => {
|
||||
export const Controls = ({ children, className }: ControlsProps) => {
|
||||
const idle = usePlayerStore((state) => state.interface.isIdle);
|
||||
const setIsIdle = usePlayerStore((state) => state.setIsIdle);
|
||||
|
||||
return <View className="flex-1 items-center">{!idle && children}</View>;
|
||||
return (
|
||||
<TouchableOpacity
|
||||
onPress={() => {
|
||||
setIsIdle(false);
|
||||
}}
|
||||
className={className}
|
||||
>
|
||||
{!idle && children}
|
||||
</TouchableOpacity>
|
||||
);
|
||||
};
|
||||
|
@@ -11,15 +11,13 @@ interface HeaderProps {
|
||||
|
||||
export const Header = ({ title }: HeaderProps) => {
|
||||
return (
|
||||
<Controls>
|
||||
<View className="absolute top-0 flex w-full flex-row items-center justify-between px-6 pt-6">
|
||||
<Controls className="absolute top-0 flex w-full flex-row items-center justify-between px-6 pt-6">
|
||||
<BackButton className="w-36" />
|
||||
<Text className="font-bold">{title}</Text>
|
||||
<View className="flex w-36 flex-row items-center justify-center gap-2 space-x-2 rounded-full bg-secondary-300 px-4 py-2 opacity-80">
|
||||
<Image source={Icon} className="h-6 w-6" />
|
||||
<Text className="font-bold">movie-web</Text>
|
||||
</View>
|
||||
</View>
|
||||
</Controls>
|
||||
);
|
||||
};
|
||||
|
21
apps/expo/src/components/player/MiddleButtons.tsx
Normal file
21
apps/expo/src/components/player/MiddleButtons.tsx
Normal file
@@ -0,0 +1,21 @@
|
||||
import { View } from "react-native";
|
||||
|
||||
import { Controls } from "./Controls";
|
||||
import { PlayButton } from "./PlayButton";
|
||||
import { SeekButton } from "./SeekButton";
|
||||
|
||||
export const MiddleControls = () => {
|
||||
return (
|
||||
<View className="absolute flex h-full w-full flex-1 flex-row items-center justify-center gap-24">
|
||||
<Controls>
|
||||
<SeekButton type="backward" />
|
||||
</Controls>
|
||||
<Controls>
|
||||
<PlayButton />
|
||||
</Controls>
|
||||
<Controls>
|
||||
<SeekButton type="forward" />
|
||||
</Controls>
|
||||
</View>
|
||||
);
|
||||
};
|
29
apps/expo/src/components/player/PlayButton.tsx
Normal file
29
apps/expo/src/components/player/PlayButton.tsx
Normal file
@@ -0,0 +1,29 @@
|
||||
import { FontAwesome } from "@expo/vector-icons";
|
||||
|
||||
import { usePlayerStore } from "~/stores/player/store";
|
||||
|
||||
export const PlayButton = () => {
|
||||
const videoRef = usePlayerStore((state) => state.videoRef);
|
||||
const status = usePlayerStore((state) => state.status);
|
||||
|
||||
return (
|
||||
<FontAwesome
|
||||
name={status?.isLoaded && status.isPlaying ? "pause" : "play"}
|
||||
size={36}
|
||||
color="white"
|
||||
onPress={() => {
|
||||
if (status?.isLoaded) {
|
||||
if (status.isPlaying) {
|
||||
videoRef?.pauseAsync().catch(() => {
|
||||
console.log("Error pausing video");
|
||||
});
|
||||
} else {
|
||||
videoRef?.playAsync().catch(() => {
|
||||
console.log("Error playing video");
|
||||
});
|
||||
}
|
||||
}
|
||||
}}
|
||||
/>
|
||||
);
|
||||
};
|
32
apps/expo/src/components/player/SeekButton.tsx
Normal file
32
apps/expo/src/components/player/SeekButton.tsx
Normal file
@@ -0,0 +1,32 @@
|
||||
import { MaterialIcons } from "@expo/vector-icons";
|
||||
|
||||
import { usePlayerStore } from "~/stores/player/store";
|
||||
|
||||
interface SeekProps {
|
||||
type: "forward" | "backward";
|
||||
}
|
||||
|
||||
export const SeekButton = ({ type }: SeekProps) => {
|
||||
const videoRef = usePlayerStore((state) => state.videoRef);
|
||||
const status = usePlayerStore((state) => state.status);
|
||||
|
||||
return (
|
||||
<MaterialIcons
|
||||
name={type === "forward" ? "forward-10" : "replay-10"}
|
||||
size={36}
|
||||
color="white"
|
||||
onPress={() => {
|
||||
if (status?.isLoaded) {
|
||||
const position =
|
||||
type === "forward"
|
||||
? status.positionMillis + 10000
|
||||
: status.positionMillis - 10000;
|
||||
|
||||
videoRef?.setPositionAsync(position).catch(() => {
|
||||
console.log("Error seeking backwards");
|
||||
});
|
||||
}
|
||||
}}
|
||||
/>
|
||||
);
|
||||
};
|
Reference in New Issue
Block a user