add more shuffle play modes

This commit is contained in:
jeffvli
2025-11-23 15:58:23 -08:00
parent 16c703fe31
commit 1763f666b5
5 changed files with 140 additions and 1 deletions
+3 -1
View File
@@ -485,6 +485,8 @@
"player": {
"addLast": "add last",
"addNext": "add next",
"addLastShuffled": "add last (shuffled)",
"addNextShuffled": "add next (shuffled)",
"favorite": "favorite",
"mute": "mute",
"muted": "muted",
@@ -509,7 +511,7 @@
"repeat_off": "repeat disabled",
"repeat_one": "repeat one",
"repeat_other": "",
"shuffle": "play shuffled",
"shuffle": "play (shuffled)",
"shuffle_off": "shuffle disabled",
"skip": "skip",
"skip_back": "skip backwards",
@@ -47,6 +47,14 @@ export const PlayAction = ({ ids, itemType, songs }: PlayActionProps) => {
handlePlay(Play.SHUFFLE);
}, [handlePlay]);
const handlePlayNextShuffled = useCallback(() => {
handlePlay(Play.NEXT_SHUFFLE);
}, [handlePlay]);
const handlePlayLastShuffled = useCallback(() => {
handlePlay(Play.LAST_SHUFFLE);
}, [handlePlay]);
const playButtonBehavior = usePlayButtonBehavior();
const defaultPlayAction = useCallback(() => {
@@ -76,9 +84,16 @@ export const PlayAction = ({ ids, itemType, songs }: PlayActionProps) => {
<ContextMenu.Item leftIcon="mediaPlayLast" onSelect={handlePlayLast}>
{t('player.addLast', { postProcess: 'sentenceCase' })}
</ContextMenu.Item>
<ContextMenu.Divider />
<ContextMenu.Item leftIcon="mediaShuffle" onSelect={handlePlayShuffled}>
{t('player.shuffle', { postProcess: 'sentenceCase' })}
</ContextMenu.Item>
<ContextMenu.Item leftIcon="mediaPlayNext" onSelect={handlePlayNextShuffled}>
{t('player.addNextShuffled', { postProcess: 'sentenceCase' })}
</ContextMenu.Item>
<ContextMenu.Item leftIcon="mediaPlayLast" onSelect={handlePlayLastShuffled}>
{t('player.addLastShuffled', { postProcess: 'sentenceCase' })}
</ContextMenu.Item>
</ContextMenu.SubmenuContent>
</ContextMenu.Submenu>
);
+117
View File
@@ -160,6 +160,34 @@ export const usePlayerStoreBase = create<PlayerState>()(
});
break;
}
case Play.LAST_SHUFFLE: {
set((state) => {
const currentIndex = state.player.index;
newItems.forEach((item) => {
state.queue.songs[item._uniqueId] = item;
});
// Shuffle the new items before appending
const shuffledIds = shuffleInPlace([...newUniqueIds]);
state.queue.default = [
...state.queue.default,
...shuffledIds,
];
if (state.player.shuffle === PlayerShuffle.TRACK) {
state.queue.shuffled = [
...state.queue.shuffled.slice(0, currentIndex),
state.queue.shuffled[currentIndex],
...shuffleInPlace([
...state.queue.shuffled.slice(currentIndex + 1),
...shuffledIds,
]),
];
}
});
break;
}
case Play.NEXT: {
set((state) => {
const currentIndex = state.player.index;
@@ -186,6 +214,35 @@ export const usePlayerStoreBase = create<PlayerState>()(
});
break;
}
case Play.NEXT_SHUFFLE: {
set((state) => {
const currentIndex = state.player.index;
newItems.forEach((item) => {
state.queue.songs[item._uniqueId] = item;
});
// Shuffle the new items before inserting
const shuffledIds = shuffleInPlace([...newUniqueIds]);
state.queue.default = [
...state.queue.default.slice(0, currentIndex + 1),
...shuffledIds,
...state.queue.default.slice(currentIndex + 1),
];
if (state.player.shuffle === PlayerShuffle.TRACK) {
state.queue.shuffled = [
...state.queue.shuffled.slice(0, currentIndex),
state.queue.shuffled[currentIndex],
...shuffleInPlace([
...state.queue.shuffled.slice(currentIndex + 1),
...shuffledIds,
]),
];
}
});
break;
}
case Play.NOW: {
set((state) => {
newItems.forEach((item) => {
@@ -252,6 +309,28 @@ export const usePlayerStoreBase = create<PlayerState>()(
});
break;
}
case Play.LAST_SHUFFLE: {
set((state) => {
// Add new songs to songs object
newItems.forEach((item) => {
state.queue.songs[item._uniqueId] = item;
});
// Shuffle the new items before appending
const shuffledIds = shuffleInPlace([...newUniqueIds]);
state.queue.priority = [
...state.queue.priority,
...shuffledIds,
];
state.queue.shuffled = [
...state.queue.shuffled,
...shuffledIds,
];
});
break;
}
case Play.NEXT: {
set((state) => {
const currentIndex = state.player.index;
@@ -287,6 +366,44 @@ export const usePlayerStoreBase = create<PlayerState>()(
});
break;
}
case Play.NEXT_SHUFFLE: {
set((state) => {
const currentIndex = state.player.index;
const isInPriority =
currentIndex < state.queue.priority.length;
// Add new songs to songs object
newItems.forEach((item) => {
state.queue.songs[item._uniqueId] = item;
});
// Shuffle the new items before inserting
const shuffledIds = shuffleInPlace([...newUniqueIds]);
if (isInPriority) {
state.queue.priority = [
...state.queue.priority.slice(0, currentIndex + 1),
...shuffledIds,
...state.queue.priority.slice(currentIndex + 1),
];
} else {
state.queue.priority = [
...state.queue.priority,
...shuffledIds,
];
}
state.queue.shuffled = [
...state.queue.shuffled.slice(0, currentIndex),
state.queue.shuffled[currentIndex],
...shuffleInPlace([
...state.queue.shuffled.slice(currentIndex + 1),
...shuffledIds,
]),
];
});
break;
}
case Play.NOW: {
set((state) => {
// Add new songs to songs object
+3
View File
@@ -0,0 +1,3 @@
import { useLongPress as useMantineLongPress } from '@mantine/hooks';
export const useLongPress = useMantineLongPress;
+2
View File
@@ -110,7 +110,9 @@ export enum FontType {
export enum Play {
INDEX = 'index',
LAST = 'last',
LAST_SHUFFLE = 'lastShuffle',
NEXT = 'next',
NEXT_SHUFFLE = 'nextShuffle',
NOW = 'now',
SHUFFLE = 'shuffle',
}