feat: add long press to shuffle with a wave animation (#888)

* feat: add long press to shuffle with a wave animation to singnify how long to press

* refactor: long-press shuffle cleanup

Follow-up on the long-press shuffle PR: shared hook/overlay, playback parity,
pointer events, broader surface coverage, locales, and tests.

* docs: credit ImAsra for long-press album shuffle (PR #888)

Add CHANGELOG entry and Settings credits for the hold-to-shuffle play
interaction shipped in Psychotoxical/psysonic#888.

* fix: restore playAlbumShuffled and long-press hook wiring

The follow-up merge dropped playAlbumShuffled and reverted the shared
long-press hook in album play buttons, breaking tsc and vitest on PR #888.

---------

Co-authored-by: cucadmuh <49571317+cucadmuh@users.noreply.github.com>
This commit is contained in:
ImAsra
2026-05-28 22:59:49 +02:00
committed by GitHub
parent 8443b3d4be
commit ae2e123a14
21 changed files with 585 additions and 44 deletions
+15 -2
View File
@@ -3,15 +3,20 @@ import { usePlayerStore } from '../../store/playerStore';
import { songToTrack } from './songToTrack';
import { useOrbitStore } from '../../store/orbitStore';
import { fadeOut } from './fadeOut';
import type { Track } from '../../store/playerStoreTypes';
import { shuffleArray } from './shuffleArray';
export async function playAlbum(albumId: string): Promise<void> {
async function fetchAlbumTracks(albumId: string): Promise<Track[]> {
const albumData = await getAlbum(albumId);
const albumGenre = albumData.album.genre;
const tracks = albumData.songs.map(s => {
return albumData.songs.map(s => {
const track = songToTrack(s);
if (!track.genre && albumGenre) track.genre = albumGenre;
return track;
});
}
async function startAlbumPlayback(tracks: Track[]): Promise<void> {
if (!tracks.length) return;
// In Orbit sessions, playAlbum is effectively an append operation (the
@@ -38,3 +43,11 @@ export async function playAlbum(albumId: string): Promise<void> {
usePlayerStore.getState().playTrack(tracks[0], tracks);
}
export async function playAlbum(albumId: string): Promise<void> {
await startAlbumPlayback(await fetchAlbumTracks(albumId));
}
export async function playAlbumShuffled(albumId: string): Promise<void> {
await startAlbumPlayback(shuffleArray(await fetchAlbumTracks(albumId)));
}