feat(playlists): queue playback in the player (auto-advance + prev/next)
PlayerModal now accepts an optional queue + startIndex. The active item drives the player; it recreates per item (reusing the single-video resume / auto-watch / progress logic), auto-advances to the next item when one ends, and shows Previous / Next controls with an N / M indicator. The Playlists page passes the playlist as the queue from Play all or a clicked row. Trilingual previous/next strings.
This commit is contained in:
parent
dea740b728
commit
4689d2cbbd
5 changed files with 99 additions and 43 deletions
|
|
@ -105,7 +105,8 @@ export default function Playlists() {
|
|||
const [renaming, setRenaming] = useState(false);
|
||||
const [renameValue, setRenameValue] = useState("");
|
||||
const [items, setItems] = useState<Video[]>([]);
|
||||
const [active, setActive] = useState<{ video: Video; startAt: number | null } | null>(null);
|
||||
// The open player, as an index into `items` (the queue); null = closed.
|
||||
const [playingIndex, setPlayingIndex] = useState<number | null>(null);
|
||||
|
||||
const listQuery = useQuery({ queryKey: ["playlists"], queryFn: () => api.playlists() });
|
||||
const playlists = listQuery.data ?? [];
|
||||
|
|
@ -312,7 +313,7 @@ export default function Playlists() {
|
|||
</div>
|
||||
<div className="flex gap-2 mt-3 flex-wrap">
|
||||
<button
|
||||
onClick={() => items[0] && setActive({ video: items[0], startAt: null })}
|
||||
onClick={() => items.length && setPlayingIndex(0)}
|
||||
disabled={!items.length}
|
||||
className="inline-flex items-center gap-1.5 text-xs font-semibold px-3 py-1.5 rounded-lg bg-accent text-accent-fg disabled:opacity-40 hover:opacity-90 transition"
|
||||
>
|
||||
|
|
@ -353,7 +354,7 @@ export default function Playlists() {
|
|||
key={v.id}
|
||||
video={v}
|
||||
index={i}
|
||||
onPlay={() => setActive({ video: v, startAt: null })}
|
||||
onPlay={() => setPlayingIndex(i)}
|
||||
onRemove={() => removeItem(v.id)}
|
||||
/>
|
||||
))}
|
||||
|
|
@ -365,11 +366,13 @@ export default function Playlists() {
|
|||
)}
|
||||
</main>
|
||||
|
||||
{active && (
|
||||
{playingIndex != null && items[playingIndex] && (
|
||||
<PlayerModal
|
||||
video={active.video}
|
||||
startAt={active.startAt}
|
||||
onClose={() => setActive(null)}
|
||||
video={items[playingIndex]}
|
||||
queue={items}
|
||||
startIndex={playingIndex}
|
||||
startAt={null}
|
||||
onClose={() => setPlayingIndex(null)}
|
||||
onState={playerState}
|
||||
/>
|
||||
)}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue