mirror of
https://github.com/Jellify-Music/App.git
synced 2026-01-06 02:50:30 -06:00
Moar hooks in the player provider to unify controls and feedback
This commit is contained in:
@@ -30,7 +30,7 @@ export default function Track({
|
||||
onPress?: () => void | undefined
|
||||
}) : React.JSX.Element {
|
||||
|
||||
const { nowPlaying, playNewQueue } = usePlayerContext();
|
||||
const { nowPlaying, usePlayNewQueue } = usePlayerContext();
|
||||
|
||||
const isPlaying = nowPlaying?.ItemId === track.Id
|
||||
|
||||
@@ -43,7 +43,7 @@ export default function Track({
|
||||
if (onPress) {
|
||||
onPress();
|
||||
} else {
|
||||
playNewQueue.mutate({
|
||||
usePlayNewQueue.mutate({
|
||||
track,
|
||||
index,
|
||||
tracklist,
|
||||
|
||||
@@ -8,7 +8,7 @@ import { usePlayerContext } from "../../../player/provider";
|
||||
|
||||
export default function RecentlyPlayed(): React.JSX.Element {
|
||||
|
||||
const { playNewQueue } = usePlayerContext();
|
||||
const { usePlayNewQueue } = usePlayerContext();
|
||||
const { apiClient, sessionId } = useApiClientContext();
|
||||
const { recentTracks } = useHomeContext();
|
||||
|
||||
@@ -25,7 +25,7 @@ export default function RecentlyPlayed(): React.JSX.Element {
|
||||
width={150}
|
||||
itemId={recentlyPlayedTrack.AlbumId!}
|
||||
onPress={() => {
|
||||
playNewQueue.mutate({
|
||||
usePlayNewQueue.mutate({
|
||||
track: recentlyPlayedTrack,
|
||||
index: index,
|
||||
tracklist: recentTracks,
|
||||
|
||||
@@ -15,12 +15,11 @@ import { queryConfig } from "../../api/queries/query.config";
|
||||
import { useApiClientContext } from "../jellyfin-api-provider";
|
||||
import TextTicker from 'react-native-text-ticker';
|
||||
import PlayPauseButton from "./helpers/buttons";
|
||||
import { skipToNext } from "react-native-track-player/lib/src/trackPlayer";
|
||||
import { useSafeAreaFrame } from "react-native-safe-area-context";
|
||||
|
||||
export function Miniplayer({ navigation }: { navigation : NavigationHelpers<ParamListBase, BottomTabNavigationEventMap> }) : React.JSX.Element {
|
||||
|
||||
const { nowPlaying } = usePlayerContext();
|
||||
const { nowPlaying, useSkip } = usePlayerContext();
|
||||
|
||||
const { apiClient } = useApiClientContext();
|
||||
|
||||
@@ -88,7 +87,7 @@ export function Miniplayer({ navigation }: { navigation : NavigationHelpers<Para
|
||||
<Icon
|
||||
large
|
||||
name="skip-next"
|
||||
onPress={() => skipToNext()}
|
||||
onPress={() => useSkip.mutate(undefined)}
|
||||
/>
|
||||
</XStack>
|
||||
</XStack>
|
||||
|
||||
@@ -10,7 +10,6 @@ import { getImageApi } from "@jellyfin/sdk/lib/utils/api";
|
||||
import { NativeStackNavigationProp } from "@react-navigation/native-stack";
|
||||
import React, { useState, useEffect } from "react";
|
||||
import { SafeAreaView, useSafeAreaFrame } from "react-native-safe-area-context";
|
||||
import { seekBy, skipToPrevious, skipToNext } from "react-native-track-player/lib/src/trackPlayer";
|
||||
import { YStack, XStack, Spacer } from "tamagui";
|
||||
import PlayPauseButton from "../helpers/buttons";
|
||||
import { H5, Text } from "@/components/Global/helpers/text";
|
||||
@@ -22,7 +21,7 @@ export default function PlayerScreen({ navigation }: { navigation: NativeStackNa
|
||||
|
||||
|
||||
const { apiClient } = useApiClientContext();
|
||||
const { playbackState, nowPlaying, progress, useSeekTo, queueName } = usePlayerContext();
|
||||
const { playbackState, nowPlaying, progress, useSeekTo, useSkip, usePrevious, queueName } = usePlayerContext();
|
||||
|
||||
const [seeking, setSeeking] = useState<boolean>(false);
|
||||
const [progressState, setProgressState] = useState<number>(progress!.position);
|
||||
@@ -160,13 +159,13 @@ export default function PlayerScreen({ navigation }: { navigation: NativeStackNa
|
||||
<XStack justifyContent="space-evenly" marginVertical={"$3"}>
|
||||
<Icon
|
||||
name="rewind-15"
|
||||
onPress={() => seekBy(-15)}
|
||||
onPress={() => useSeekTo.mutate(progress!.position - 15)}
|
||||
/>
|
||||
|
||||
<Icon
|
||||
large
|
||||
name="skip-previous"
|
||||
onPress={() => skipToPrevious()}
|
||||
onPress={() => usePrevious.mutate()}
|
||||
/>
|
||||
|
||||
<PlayPauseButton />
|
||||
@@ -174,12 +173,12 @@ export default function PlayerScreen({ navigation }: { navigation: NativeStackNa
|
||||
<Icon
|
||||
large
|
||||
name="skip-next"
|
||||
onPress={() => skipToNext()}
|
||||
onPress={() => useSkip.mutate(undefined)}
|
||||
/>
|
||||
|
||||
<Icon
|
||||
name="fast-forward-15"
|
||||
onPress={() => seekBy(15)}
|
||||
onPress={() => useSeekTo.mutate(progress!.position + 15)}
|
||||
/>
|
||||
</XStack>
|
||||
|
||||
|
||||
@@ -2,11 +2,10 @@ import Track from "@/components/Global/components/track";
|
||||
import { usePlayerContext } from "@/player/provider";
|
||||
import { FlatList } from "react-native";
|
||||
import { SafeAreaView } from "react-native-safe-area-context";
|
||||
import { skip } from "react-native-track-player/lib/src/trackPlayer";
|
||||
|
||||
export default function Queue(): React.JSX.Element {
|
||||
|
||||
const { queue } = usePlayerContext();
|
||||
const { queue, useSkip } = usePlayerContext();
|
||||
|
||||
return (
|
||||
<SafeAreaView edges={["right", "left"]}>
|
||||
@@ -21,7 +20,7 @@ export default function Queue(): React.JSX.Element {
|
||||
index={index}
|
||||
showArtwork
|
||||
onPress={() => {
|
||||
skip(index);
|
||||
useSkip.mutate(index);
|
||||
}}
|
||||
/>
|
||||
)
|
||||
|
||||
@@ -17,7 +17,7 @@ import { QueueMutation } from "./interfaces";
|
||||
import { mapDtoToTrack } from "@/helpers/mappings";
|
||||
import { QueuingType } from "@/enums/queuing-type";
|
||||
import { trigger } from "react-native-haptic-feedback";
|
||||
import { pause, seekTo } from "react-native-track-player/lib/src/trackPlayer";
|
||||
import { pause, seekTo, skip, skipToNext, skipToPrevious } from "react-native-track-player/lib/src/trackPlayer";
|
||||
import { convertRunTimeTicksToSeconds } from "@/helpers/runtimeticks";
|
||||
|
||||
interface PlayerContext {
|
||||
@@ -30,7 +30,9 @@ interface PlayerContext {
|
||||
queueName: string | undefined;
|
||||
useTogglePlayback: UseMutationResult<void, Error, number | undefined, unknown>;
|
||||
useSeekTo: UseMutationResult<void, Error, number, unknown>;
|
||||
playNewQueue: UseMutationResult<void, Error, QueueMutation, unknown>;
|
||||
useSkip: UseMutationResult<void, Error, number | undefined, unknown>;
|
||||
usePrevious: UseMutationResult<void, Error, void, unknown>;
|
||||
usePlayNewQueue: UseMutationResult<void, Error, QueueMutation, unknown>;
|
||||
playbackState: State | undefined;
|
||||
progress: Progress | undefined;
|
||||
}
|
||||
@@ -97,7 +99,7 @@ const PlayerContextInitializer = () => {
|
||||
trigger('impactLight');
|
||||
await seekTo(position);
|
||||
|
||||
await handlePlaybackProgressUpdated(sessionId, playStateApi, nowPlaying!, {
|
||||
handlePlaybackProgressUpdated(sessionId, playStateApi, nowPlaying!, {
|
||||
buffered: 0,
|
||||
position,
|
||||
duration: convertRunTimeTicksToSeconds(nowPlaying!.duration!)
|
||||
@@ -105,7 +107,24 @@ const PlayerContextInitializer = () => {
|
||||
}
|
||||
});
|
||||
|
||||
const playNewQueue = useMutation({
|
||||
const useSkip = useMutation({
|
||||
mutationFn: async (index?: number) => {
|
||||
trigger("impactLight")
|
||||
if (index)
|
||||
skip(index)
|
||||
else
|
||||
skipToNext();
|
||||
}
|
||||
});
|
||||
|
||||
const usePrevious = useMutation({
|
||||
mutationFn: async () => {
|
||||
trigger("impactLight")
|
||||
await skipToPrevious();
|
||||
}
|
||||
})
|
||||
|
||||
const usePlayNewQueue = useMutation({
|
||||
mutationFn: async (mutation: QueueMutation) => {
|
||||
trigger("impactLight");
|
||||
await resetQueue(false);
|
||||
@@ -184,7 +203,9 @@ const PlayerContextInitializer = () => {
|
||||
queueName,
|
||||
useTogglePlayback,
|
||||
useSeekTo,
|
||||
playNewQueue,
|
||||
useSkip,
|
||||
usePrevious,
|
||||
usePlayNewQueue,
|
||||
playbackState,
|
||||
progress,
|
||||
}
|
||||
@@ -236,7 +257,43 @@ export const PlayerContext = createContext<PlayerContext>({
|
||||
failureReason: null,
|
||||
submittedAt: 0
|
||||
},
|
||||
playNewQueue: {
|
||||
useSkip: {
|
||||
mutate: () => {},
|
||||
mutateAsync: async () => {},
|
||||
data: undefined,
|
||||
error: null,
|
||||
variables: undefined,
|
||||
isError: false,
|
||||
isIdle: true,
|
||||
isPaused: false,
|
||||
isPending: false,
|
||||
isSuccess: false,
|
||||
status: "idle",
|
||||
reset: () => {},
|
||||
context: {},
|
||||
failureCount: 0,
|
||||
failureReason: null,
|
||||
submittedAt: 0
|
||||
},
|
||||
usePrevious: {
|
||||
mutate: () => {},
|
||||
mutateAsync: async () => {},
|
||||
data: undefined,
|
||||
error: null,
|
||||
variables: undefined,
|
||||
isError: false,
|
||||
isIdle: true,
|
||||
isPaused: false,
|
||||
isPending: false,
|
||||
isSuccess: false,
|
||||
status: "idle",
|
||||
reset: () => {},
|
||||
context: {},
|
||||
failureCount: 0,
|
||||
failureReason: null,
|
||||
submittedAt: 0
|
||||
},
|
||||
usePlayNewQueue: {
|
||||
mutate: () => {},
|
||||
mutateAsync: async () => {},
|
||||
data: undefined,
|
||||
@@ -270,7 +327,9 @@ export const PlayerProvider: ({ children }: { children: ReactNode }) => React.JS
|
||||
queueName,
|
||||
useTogglePlayback,
|
||||
useSeekTo,
|
||||
playNewQueue,
|
||||
useSkip,
|
||||
usePrevious,
|
||||
usePlayNewQueue,
|
||||
playbackState,
|
||||
progress
|
||||
} = PlayerContextInitializer();
|
||||
@@ -285,7 +344,9 @@ export const PlayerProvider: ({ children }: { children: ReactNode }) => React.JS
|
||||
queueName,
|
||||
useTogglePlayback,
|
||||
useSeekTo,
|
||||
playNewQueue,
|
||||
useSkip,
|
||||
usePrevious,
|
||||
usePlayNewQueue,
|
||||
playbackState,
|
||||
progress
|
||||
}}>
|
||||
|
||||
Reference in New Issue
Block a user