feat: add context menu to Playlist for adding tracks to play next queue
This commit is contained in:
@@ -3,11 +3,17 @@ import { Badge } from '@/components/ui/badge'
|
|||||||
import { Button } from '@/components/ui/button'
|
import { Button } from '@/components/ui/button'
|
||||||
import { Input } from '@/components/ui/input'
|
import { Input } from '@/components/ui/input'
|
||||||
import { ScrollArea } from '@/components/ui/scroll-area'
|
import { ScrollArea } from '@/components/ui/scroll-area'
|
||||||
|
import {
|
||||||
|
ContextMenu,
|
||||||
|
ContextMenuContent,
|
||||||
|
ContextMenuItem,
|
||||||
|
ContextMenuTrigger,
|
||||||
|
} from '@/components/ui/context-menu'
|
||||||
import { filesService } from '@/lib/api/services/files'
|
import { filesService } from '@/lib/api/services/files'
|
||||||
import { type PlayerPlaylist } from '@/lib/api/services/player'
|
import { type PlayerPlaylist, playerService } from '@/lib/api/services/player'
|
||||||
import { cn } from '@/lib/utils'
|
import { cn } from '@/lib/utils'
|
||||||
import { formatDuration } from '@/utils/format-duration'
|
import { formatDuration } from '@/utils/format-duration'
|
||||||
import { Music, Play, Search, X } from 'lucide-react'
|
import { Music, Play, Search, X, ListPlus } from 'lucide-react'
|
||||||
|
|
||||||
interface PlaylistProps {
|
interface PlaylistProps {
|
||||||
playlist: PlayerPlaylist
|
playlist: PlayerPlaylist
|
||||||
@@ -28,6 +34,14 @@ export function Playlist({
|
|||||||
sound.name.toLowerCase().includes(searchQuery.toLowerCase())
|
sound.name.toLowerCase().includes(searchQuery.toLowerCase())
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const handleAddToPlayNext = async (soundId: number) => {
|
||||||
|
try {
|
||||||
|
await playerService.addToPlayNext(soundId)
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Failed to add track to play next:', error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="w-full">
|
<div className="w-full">
|
||||||
{/* Header */}
|
{/* Header */}
|
||||||
@@ -68,8 +82,9 @@ export function Playlist({
|
|||||||
{filteredSounds.map((sound) => {
|
{filteredSounds.map((sound) => {
|
||||||
const originalIndex = playlist.sounds.findIndex((s) => s.id === sound.id)
|
const originalIndex = playlist.sounds.findIndex((s) => s.id === sound.id)
|
||||||
return (
|
return (
|
||||||
|
<ContextMenu key={sound.id}>
|
||||||
|
<ContextMenuTrigger asChild>
|
||||||
<div
|
<div
|
||||||
key={sound.id}
|
|
||||||
className={cn(
|
className={cn(
|
||||||
'grid grid-cols-10 gap-2 items-center py-1.5 px-2 rounded hover:bg-muted/50 cursor-pointer text-xs',
|
'grid grid-cols-10 gap-2 items-center py-1.5 px-2 rounded hover:bg-muted/50 cursor-pointer text-xs',
|
||||||
currentIndex === originalIndex && 'bg-primary/10 text-primary',
|
currentIndex === originalIndex && 'bg-primary/10 text-primary',
|
||||||
@@ -125,6 +140,14 @@ export function Playlist({
|
|||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</ContextMenuTrigger>
|
||||||
|
<ContextMenuContent>
|
||||||
|
<ContextMenuItem onClick={() => handleAddToPlayNext(sound.id)}>
|
||||||
|
<ListPlus className="mr-2 h-4 w-4" />
|
||||||
|
Add to play next
|
||||||
|
</ContextMenuItem>
|
||||||
|
</ContextMenuContent>
|
||||||
|
</ContextMenu>
|
||||||
)})}
|
)})}
|
||||||
</div>
|
</div>
|
||||||
</ScrollArea>
|
</ScrollArea>
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ export interface PlayerState {
|
|||||||
index?: number
|
index?: number
|
||||||
current_sound?: PlayerSound
|
current_sound?: PlayerSound
|
||||||
playlist?: PlayerPlaylist
|
playlist?: PlayerPlaylist
|
||||||
|
play_next_queue: PlayerSound[]
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface PlayerSeekRequest {
|
export interface PlayerSeekRequest {
|
||||||
@@ -147,6 +148,13 @@ export class PlayerService {
|
|||||||
async getState(): Promise<PlayerState> {
|
async getState(): Promise<PlayerState> {
|
||||||
return apiClient.get<PlayerState>('/api/v1/player/state')
|
return apiClient.get<PlayerState>('/api/v1/player/state')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a sound to the play next queue
|
||||||
|
*/
|
||||||
|
async addToPlayNext(soundId: number): Promise<MessageResponse> {
|
||||||
|
return apiClient.post<MessageResponse>(`/api/v1/player/play-next/${soundId}`)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const playerService = new PlayerService()
|
export const playerService = new PlayerService()
|
||||||
|
|||||||
Reference in New Issue
Block a user