From 4121502bfe6d159206f629efebde09d0b1b125c2 Mon Sep 17 00:00:00 2001 From: Fredrik Burmester Date: Sun, 4 Jan 2026 13:44:53 +0100 Subject: [PATCH] fix: remove song from playlist --- .../music/playlist/[playlistId].tsx | 14 ++++++++++ components/music/TrackOptionsSheet.tsx | 26 +++++++++++++++++++ hooks/usePlaylistMutations.ts | 3 +++ translations/en.json | 3 ++- 4 files changed, 45 insertions(+), 1 deletion(-) diff --git a/app/(auth)/(tabs)/(home,libraries,search,favorites,watchlists)/music/playlist/[playlistId].tsx b/app/(auth)/(tabs)/(home,libraries,search,favorites,watchlists)/music/playlist/[playlistId].tsx index ab32a235..4a8dabd4 100644 --- a/app/(auth)/(tabs)/(home,libraries,search,favorites,watchlists)/music/playlist/[playlistId].tsx +++ b/app/(auth)/(tabs)/(home,libraries,search,favorites,watchlists)/music/playlist/[playlistId].tsx @@ -21,6 +21,7 @@ import { CreatePlaylistModal } from "@/components/music/CreatePlaylistModal"; import { MusicTrackItem } from "@/components/music/MusicTrackItem"; import { PlaylistPickerSheet } from "@/components/music/PlaylistPickerSheet"; import { TrackOptionsSheet } from "@/components/music/TrackOptionsSheet"; +import { useRemoveFromPlaylist } from "@/hooks/usePlaylistMutations"; import { downloadTrack, getLocalPath } from "@/providers/AudioStorage"; import { apiAtom, userAtom } from "@/providers/JellyfinProvider"; import { useMusicPlayer } from "@/providers/MusicPlayerProvider"; @@ -46,6 +47,8 @@ export default function PlaylistDetailScreen() { const [createPlaylistOpen, setCreatePlaylistOpen] = useState(false); const [isDownloading, setIsDownloading] = useState(false); + const removeFromPlaylist = useRemoveFromPlaylist(); + const handleTrackOptionsPress = useCallback((track: BaseItemDto) => { setSelectedTrack(track); setTrackOptionsOpen(true); @@ -59,6 +62,15 @@ export default function PlaylistDetailScreen() { setCreatePlaylistOpen(true); }, []); + const handleRemoveFromPlaylist = useCallback(() => { + if (selectedTrack?.Id && playlistId) { + removeFromPlaylist.mutate({ + playlistId, + entryIds: [selectedTrack.PlaylistItemId ?? selectedTrack.Id], + }); + } + }, [selectedTrack, playlistId, removeFromPlaylist]); + const { data: playlist, isLoading: loadingPlaylist } = useQuery({ queryKey: ["music-playlist", playlistId, user?.Id], queryFn: async () => { @@ -269,6 +281,8 @@ export default function PlaylistDetailScreen() { setOpen={setTrackOptionsOpen} track={selectedTrack} onAddToPlaylist={handleAddToPlaylist} + playlistId={playlistId} + onRemoveFromPlaylist={handleRemoveFromPlaylist} /> void; track: BaseItemDto | null; onAddToPlaylist: () => void; + playlistId?: string; + onRemoveFromPlaylist?: () => void; } export const TrackOptionsSheet: React.FC = ({ @@ -49,6 +51,8 @@ export const TrackOptionsSheet: React.FC = ({ setOpen, track, onAddToPlaylist, + playlistId, + onRemoveFromPlaylist, }) => { const bottomSheetModalRef = useRef(null); const [api] = useAtom(apiAtom); @@ -132,6 +136,13 @@ export const TrackOptionsSheet: React.FC = ({ }, 300); }, [onAddToPlaylist, setOpen]); + const handleRemoveFromPlaylist = useCallback(() => { + if (onRemoveFromPlaylist) { + onRemoveFromPlaylist(); + setOpen(false); + } + }, [onRemoveFromPlaylist, setOpen]); + const handleDownload = useCallback(async () => { if (!track?.Id || !api || !user?.Id || isAlreadyDownloaded) return; @@ -298,6 +309,21 @@ export const TrackOptionsSheet: React.FC = ({ + {playlistId && ( + <> + + + + + {t("music.track_options.remove_from_playlist")} + + + + )} + { queryClient.invalidateQueries({ queryKey: ["music-playlist", variables.playlistId], }); + queryClient.invalidateQueries({ + queryKey: ["music-playlist-tracks", variables.playlistId], + }); if (variables.playlistName) { toast.success( t("music.playlists.removed_from", { name: variables.playlistName }), diff --git a/translations/en.json b/translations/en.json index da3d5a7f..a45fc60b 100644 --- a/translations/en.json +++ b/translations/en.json @@ -653,7 +653,8 @@ "go_to_artist": "Go to Artist", "go_to_album": "Go to Album", "add_to_favorites": "Add to Favorites", - "remove_from_favorites": "Remove from Favorites" + "remove_from_favorites": "Remove from Favorites", + "remove_from_playlist": "Remove from Playlist" }, "playlists": { "create_playlist": "Create Playlist",