should be able to add a track to a playlist now

also moar haptic feedback all around
This commit is contained in:
Violet Caulfield
2025-02-05 18:57:57 -06:00
parent c7a5f4c7d8
commit abb61a42a4
6 changed files with 91 additions and 18 deletions

View File

@@ -1,7 +1,16 @@
import { BaseItemDto } from "@jellyfin/sdk/lib/generated-client/models";
import Client from "../../../api/client";
import { getPlaylistsApi } from "@jellyfin/sdk/lib/utils/api";
export async function addToPlaylist(track: BaseItemDto, playlist: BaseItemDto) {
return getPlaylistsApi(Client.api!)
.addItemToPlaylist({
ids: [
track.Id!
],
playlistId: playlist.Id!
})
}
export async function reorderPlaylist(playlistId: string, itemId: string, to: number) {
return getPlaylistsApi(Client.api!)

View File

@@ -10,6 +10,7 @@ import Client from "../../../api/client";
import { usePlayerContext } from "../../..//player/provider";
import { queryClient } from "../../../constants/query-client";
import { QueryKeys } from "../../../enums/query-keys";
import { trigger } from "react-native-haptic-feedback";
interface SetFavoriteMutation {
item: BaseItemDto,
@@ -37,6 +38,8 @@ export default function FavoriteButton({
})
},
onSuccess: () => {
trigger("notificationSuccess");
setIsFavorite(true);
onToggle ? onToggle() : {};
@@ -48,11 +51,7 @@ export default function FavoriteButton({
if (item.Type === 'Audio') {
queryClient.invalidateQueries({
queryKey: [QueryKeys.AlbumTracks]
});
queryClient.invalidateQueries({
queryKey: [QueryKeys.Playlist]
queryKey: [QueryKeys.ItemTracks]
});
}
}

View File

@@ -32,7 +32,7 @@ export default function ItemDetail({
switch (item.Type) {
case "Audio": {
options = TrackOptions({ item, navigation, isNested });
options = TrackOptions({ track: item, navigation, isNested });
break;
}

View File

@@ -3,15 +3,23 @@ import { useItem } from "../../../api/queries/item";
import { StackParamList } from "../../../components/types";
import { BaseItemDto } from "@jellyfin/sdk/lib/generated-client/models";
import { NativeStackNavigationProp } from "@react-navigation/native-stack";
import { Spacer, Spinner, XStack, YGroup, YStack } from "tamagui";
import { ListItem, Spacer, Spinner, XStack, YGroup, YStack } from "tamagui";
import { QueuingType } from "../../../enums/queuing-type";
import { useSafeAreaFrame } from "react-native-safe-area-context";
import IconButton from "../../../components/Global/helpers/icon-button";
import { Text } from "../../../components/Global/helpers/text";
import { useUserPlaylists } from "../../../api/queries/playlist";
import React from "react";
import BlurhashedImage from "@/components/Global/components/blurhashed-image";
import { useMutation } from "@tanstack/react-query";
import { AddToPlaylistMutation } from "../types";
import { addToPlaylist } from "@/api/mutations/functions/playlists";
import { trigger } from "react-native-haptic-feedback";
import { queryClient } from "@/constants/query-client";
import { QueryKeys } from "@/enums/query-keys";
interface TrackOptionsProps {
item: BaseItemDto;
track: BaseItemDto;
navigation: NativeStackNavigationProp<StackParamList>;
/**
@@ -21,12 +29,12 @@ interface TrackOptionsProps {
}
export default function TrackOptions({
item,
track,
navigation,
isNested
} : TrackOptionsProps) : React.JSX.Element {
const { data: album, isSuccess: albumFetchSuccess } = useItem(item.AlbumId ?? "");
const { data: album, isSuccess: albumFetchSuccess } = useItem(track.AlbumId ?? "");
const { data: playlists, isPending : playlistsFetchPending, isSuccess: playlistsFetchSuccess } = useUserPlaylists();
@@ -64,7 +72,7 @@ export default function TrackOptions({
title="Play Next"
onPress={() => {
useAddToQueue.mutate({
track: item,
track: track,
queuingType: QueuingType.PlayingNext
})
}}
@@ -77,21 +85,72 @@ export default function TrackOptions({
title="Queue"
onPress={() => {
useAddToQueue.mutate({
track: item
track: track
})
}}
size={width / 5}
/>
</XStack>
<Spacer />
{ playlistsFetchPending && (
<Spinner />
)}
<Text bold>Add to Playlist</Text>
<YGroup>
{ playlists?.map}
</YGroup>
{ playlistsFetchSuccess && (
<>
<Text
bold
fontSize={"$6"}
>
Add to Playlist
</Text>
<YGroup>
{ playlists.map(playlist => {
const useAddToPlaylist = useMutation({
mutationFn: ({ track, playlist }: AddToPlaylistMutation) => {
return addToPlaylist(track, playlist)
},
onSuccess: (data, { playlist }) => {
trigger("notificationSuccess")
queryClient.invalidateQueries({
queryKey: [QueryKeys.ItemTracks, playlist.Id!, false],
exact: true
});
},
onError: () => {
trigger("notificationError")
}
})
return (
<YGroup.Item>
<ListItem hoverTheme onPress={() => {
useAddToPlaylist.mutate({
track,
playlist
})
}}>
<XStack>
<BlurhashedImage
item={playlist}
width={width / 6}
/>
<Text bold fontSize={"$6"}>{playlist.Name ?? "Untitled Playlist"}</Text>
</XStack>
</ListItem>
</YGroup.Item>
)
})}
</YGroup>
</>
)}
</YStack>
)
}

View File

@@ -0,0 +1,6 @@
import { BaseItemDto } from "@jellyfin/sdk/lib/generated-client/models";
export interface AddToPlaylistMutation {
track: BaseItemDto;
playlist: BaseItemDto;
}

View File

@@ -6,4 +6,4 @@ export const queryClient = new QueryClient({
gcTime: (1000 * 60 * 24 * 24) * 5 // 5 days
}
}
})
});