a simple web player for subsonic tinysub.devins.page
subsonic navidrome javascript
9
fork

Configure Feed

Select the types of activity you want to include in your feed.

feat: implement queue snapshotting

before queue mutations, store the state of the queue into the queue
history manager.

Signed-off-by: oppiliappan <me@oppi.li>

authored by

oppiliappan and committed by
Tangled
99b4e72b 64c562ed

+33
+33
src/js/queue.js
··· 1 1 // queue management, sorting, virtual scrolling, and track display 2 2 3 + class QueueSnapshot { 4 + static create(queue, queueIndex) { 5 + return { 6 + queue: structuredClone(queue), 7 + queueIndex, 8 + timestamp: Date.now(), 9 + }; 10 + } 11 + 12 + static apply(snapshot, state) { 13 + state.queue = structuredClone(snapshot.queue); 14 + state.queueIndex = snapshot.queueIndex; 15 + } 16 + } 17 + 18 + // create snapshot of current queue state 19 + function snapshotQueue() { 20 + return QueueSnapshot.create(state.queue, state.queueIndex); 21 + } 22 + 23 + // restore queue state from snapshot and update UI 24 + function restoreQueue(snapshot) { 25 + if (!snapshot) return; 26 + QueueSnapshot.apply(snapshot, state); 27 + updateQueue(); 28 + } 29 + 3 30 // sort or shuffle queue, preserving current track position 4 31 // if items are selected, only sorts selected items, otherwise sorts entire queue 5 32 function sortQueue(field, ascending) { 33 + history.saveState(snapshotQueue()); 6 34 const currentTrack = 7 35 state.queueIndex >= 0 ? state.queue[state.queueIndex] : null; 8 36 const selectedIndices = queueSelection?.getSelected() ?? []; ··· 144 172 145 173 // move items within queue 146 174 function moveQueueItems(queue, selectedIndices, insertPos, callbacks = {}) { 175 + history.saveState(snapshotQueue()); 147 176 const { onSelectionChange, onQueueChange } = callbacks; 148 177 const sortedIndices = Array.from(selectedIndices).sort((a, b) => a - b); 149 178 const movedItems = sortedIndices.map((i) => queue[i]); ··· 221 250 222 251 // add songs to queue 223 252 async function addToQueue(fetcher, songExtractor, insertNext = false) { 253 + history.saveState(snapshotQueue()); 224 254 const songs = await songExtractor(await fetcher()); 225 255 songs.forEach((song) => { 226 256 if (song.userRating && song.userRating > 0) { ··· 293 323 294 324 // clear selected rows 295 325 function clearSelectedRows() { 326 + history.saveState(snapshotQueue()); 296 327 const toRemove = queueSelection.getSelected(); 297 328 if (toRemove.length === 0) return; 298 329 ··· 328 359 329 360 // remove a song by index, adjusting queue index if necessary 330 361 function removeFromQueue(idx) { 362 + history.saveState(snapshotQueue()); 331 363 const isCurrentTrack = idx === state.queueIndex; 332 364 333 365 state.queue.splice(idx, 1); ··· 375 407 376 408 // remove all items from queue 377 409 function clearQueue() { 410 + history.saveState(snapshotQueue()); 378 411 state.queue = []; 379 412 state.queueIndex = -1; 380 413 saveQueue();