diff --git a/src/player/PlayerController.ts b/src/player/PlayerController.ts index b7fa9c28..31480ef3 100644 --- a/src/player/PlayerController.ts +++ b/src/player/PlayerController.ts @@ -1116,6 +1116,7 @@ export class PlayerController { } this.queue.replaceAutomaticUpcoming(recommendations); + this.emit(); } private async refreshRestoredTrackMetadata(track: Track, restoreRequestId: number): Promise { diff --git a/src/ui/components/TrackContextMenu.tsx b/src/ui/components/TrackContextMenu.tsx index 410b0b34..d271a494 100644 --- a/src/ui/components/TrackContextMenu.tsx +++ b/src/ui/components/TrackContextMenu.tsx @@ -8,7 +8,7 @@ import { useState, useSyncExternalStore, } from "react"; -import { AlbumIcon, CheckIcon, CloseIcon, CompassIcon, DownloadIcon, HeartActiveIcon, HeartIcon, LinkIcon, ListIcon, PencilIcon, PlaylistAddIcon, PlaylistIcon, SearchIcon, SkipNextIcon, TrashIcon } from "@/ui/icons"; +import { AlbumIcon, CheckIcon, CloseIcon, CompassIcon, DownloadIcon, HeartActiveIcon, HeartIcon, LinkIcon, ListIcon, PencilIcon, PlaylistAddIcon, PlaylistIcon, RadioIcon, SearchIcon, SkipNextIcon, TrashIcon } from "@/ui/icons"; import type { Playlist, Track, TrackRating } from "../../datasource/types"; import { TrackContextMenuContext, @@ -303,6 +303,13 @@ export function TrackContextMenuProvider({ showToast(`"${track.title}" will play next`); }; + /** Plays the track solo and lets autoplay fill the rest, seeded from it — a YT Music mix. */ + const startRadio = () => { + if (!track) return; + setMenuPosition(null); + void playerController.playTrackById(track.id, [track], true); + }; + const copyLink = async () => { if (!track) return; const selectedTrack = track; @@ -556,6 +563,13 @@ export function TrackContextMenuProvider({