hasNext: player.qi + 1 < player.queue.length || player.repeat > 0, hasPrev: true, }; /* the window, clamped at both ends. `at` is recomputed rather than assumed to be QUEUE_WINDOW: at the top of the queue the slice starts at 0 and the current item is the first entry, not the eleventh. */ const lo = Math.max(0, player.qi - QUEUE_WINDOW); const win = player.qi < 0 ? [] : player.queue.slice(lo, player.qi + QUEUE_WINDOW + 1); const at = player.qi - lo; state.queue = win.map(windowItem); state.queueIndex = at >= 0 && at < win.length ? at : null;