add shuffle context menu item
This commit is contained in:
parent
42ba5a531c
commit
fbac33ceba
7 changed files with 73 additions and 12 deletions
|
@ -333,6 +333,7 @@
|
||||||
"removeFromPlaylist": "$t(action.removeFromPlaylist)",
|
"removeFromPlaylist": "$t(action.removeFromPlaylist)",
|
||||||
"removeFromQueue": "$t(action.removeFromQueue)",
|
"removeFromQueue": "$t(action.removeFromQueue)",
|
||||||
"setRating": "$t(action.setRating)",
|
"setRating": "$t(action.setRating)",
|
||||||
|
"playShuffled": "$t(player.shuffle)",
|
||||||
"shareItem": "share item",
|
"shareItem": "share item",
|
||||||
"showDetails": "get info"
|
"showDetails": "get info"
|
||||||
},
|
},
|
||||||
|
@ -438,7 +439,7 @@
|
||||||
"repeat_off": "repeat disabled",
|
"repeat_off": "repeat disabled",
|
||||||
"repeat_one": "repeat one",
|
"repeat_one": "repeat one",
|
||||||
"repeat_other": "",
|
"repeat_other": "",
|
||||||
"shuffle": "shuffle",
|
"shuffle": "play shuffled",
|
||||||
"shuffle_off": "shuffle disabled",
|
"shuffle_off": "shuffle disabled",
|
||||||
"skip": "skip",
|
"skip": "skip",
|
||||||
"skip_back": "skip backwards",
|
"skip_back": "skip backwards",
|
||||||
|
@ -591,6 +592,7 @@
|
||||||
"playButtonBehavior_optionAddLast": "$t(player.addLast)",
|
"playButtonBehavior_optionAddLast": "$t(player.addLast)",
|
||||||
"playButtonBehavior_optionAddNext": "$t(player.addNext)",
|
"playButtonBehavior_optionAddNext": "$t(player.addNext)",
|
||||||
"playButtonBehavior_optionPlay": "$t(player.play)",
|
"playButtonBehavior_optionPlay": "$t(player.play)",
|
||||||
|
"playButtonBehavior_optionPlayShuffled": "$t(player.shuffle)",
|
||||||
"playerAlbumArtResolution": "player album art resolution",
|
"playerAlbumArtResolution": "player album art resolution",
|
||||||
"playerAlbumArtResolution_description": "the resolution for the large player's album art preview. larger makes it look more crisp, but may slow loading down. defaults to 0, meaning auto",
|
"playerAlbumArtResolution_description": "the resolution for the large player's album art preview. larger makes it look more crisp, but may slow loading down. defaults to 0, meaning auto",
|
||||||
"playerbarOpenDrawer": "playerbar fullscreen toggle",
|
"playerbarOpenDrawer": "playerbar fullscreen toggle",
|
||||||
|
|
|
@ -18,6 +18,7 @@ export const SONG_CONTEXT_MENU_ITEMS: SetContextMenuItems = [
|
||||||
{ id: 'play' },
|
{ id: 'play' },
|
||||||
{ id: 'playLast' },
|
{ id: 'playLast' },
|
||||||
{ id: 'playNext' },
|
{ id: 'playNext' },
|
||||||
|
{ id: 'playShuffled' },
|
||||||
{ divider: true, id: 'playSimilarSongs' },
|
{ divider: true, id: 'playSimilarSongs' },
|
||||||
{ divider: true, id: 'addToPlaylist' },
|
{ divider: true, id: 'addToPlaylist' },
|
||||||
{ id: 'addToFavorites' },
|
{ id: 'addToFavorites' },
|
||||||
|
@ -31,7 +32,8 @@ export const SONG_CONTEXT_MENU_ITEMS: SetContextMenuItems = [
|
||||||
export const SONG_ALBUM_PAGE: SetContextMenuItems = [
|
export const SONG_ALBUM_PAGE: SetContextMenuItems = [
|
||||||
{ id: 'play' },
|
{ id: 'play' },
|
||||||
{ id: 'playLast' },
|
{ id: 'playLast' },
|
||||||
{ divider: true, id: 'playNext' },
|
{ id: 'playNext' },
|
||||||
|
{ divider: true, id: 'playShuffled' },
|
||||||
{ divider: true, id: 'addToPlaylist' },
|
{ divider: true, id: 'addToPlaylist' },
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -39,6 +41,7 @@ export const PLAYLIST_SONG_CONTEXT_MENU_ITEMS: SetContextMenuItems = [
|
||||||
{ id: 'play' },
|
{ id: 'play' },
|
||||||
{ id: 'playLast' },
|
{ id: 'playLast' },
|
||||||
{ id: 'playNext' },
|
{ id: 'playNext' },
|
||||||
|
{ id: 'playShuffled' },
|
||||||
{ divider: true, id: 'playSimilarSongs' },
|
{ divider: true, id: 'playSimilarSongs' },
|
||||||
{ id: 'addToPlaylist' },
|
{ id: 'addToPlaylist' },
|
||||||
{ divider: true, id: 'removeFromPlaylist' },
|
{ divider: true, id: 'removeFromPlaylist' },
|
||||||
|
@ -54,6 +57,7 @@ export const SMART_PLAYLIST_SONG_CONTEXT_MENU_ITEMS: SetContextMenuItems = [
|
||||||
{ id: 'play' },
|
{ id: 'play' },
|
||||||
{ id: 'playLast' },
|
{ id: 'playLast' },
|
||||||
{ id: 'playNext' },
|
{ id: 'playNext' },
|
||||||
|
{ divider: true, id: 'playShuffled' },
|
||||||
{ divider: true, id: 'playSimilarSongs' },
|
{ divider: true, id: 'playSimilarSongs' },
|
||||||
{ divider: true, id: 'addToPlaylist' },
|
{ divider: true, id: 'addToPlaylist' },
|
||||||
{ id: 'addToFavorites' },
|
{ id: 'addToFavorites' },
|
||||||
|
@ -67,7 +71,8 @@ export const SMART_PLAYLIST_SONG_CONTEXT_MENU_ITEMS: SetContextMenuItems = [
|
||||||
export const ALBUM_CONTEXT_MENU_ITEMS: SetContextMenuItems = [
|
export const ALBUM_CONTEXT_MENU_ITEMS: SetContextMenuItems = [
|
||||||
{ id: 'play' },
|
{ id: 'play' },
|
||||||
{ id: 'playLast' },
|
{ id: 'playLast' },
|
||||||
{ divider: true, id: 'playNext' },
|
{ id: 'playNext' },
|
||||||
|
{ divider: true, id: 'playShuffled' },
|
||||||
{ divider: true, id: 'addToPlaylist' },
|
{ divider: true, id: 'addToPlaylist' },
|
||||||
{ id: 'addToFavorites' },
|
{ id: 'addToFavorites' },
|
||||||
{ id: 'removeFromFavorites' },
|
{ id: 'removeFromFavorites' },
|
||||||
|
@ -79,14 +84,16 @@ export const ALBUM_CONTEXT_MENU_ITEMS: SetContextMenuItems = [
|
||||||
export const GENRE_CONTEXT_MENU_ITEMS: SetContextMenuItems = [
|
export const GENRE_CONTEXT_MENU_ITEMS: SetContextMenuItems = [
|
||||||
{ id: 'play' },
|
{ id: 'play' },
|
||||||
{ id: 'playLast' },
|
{ id: 'playLast' },
|
||||||
{ divider: true, id: 'playNext' },
|
{ id: 'playNext' },
|
||||||
|
{ divider: true, id: 'playShuffled' },
|
||||||
{ divider: true, id: 'addToPlaylist' },
|
{ divider: true, id: 'addToPlaylist' },
|
||||||
];
|
];
|
||||||
|
|
||||||
export const ARTIST_CONTEXT_MENU_ITEMS: SetContextMenuItems = [
|
export const ARTIST_CONTEXT_MENU_ITEMS: SetContextMenuItems = [
|
||||||
{ id: 'play' },
|
{ id: 'play' },
|
||||||
{ id: 'playLast' },
|
{ id: 'playLast' },
|
||||||
{ divider: true, id: 'playNext' },
|
{ id: 'playNext' },
|
||||||
|
{ divider: true, id: 'playShuffled' },
|
||||||
{ divider: true, id: 'addToPlaylist' },
|
{ divider: true, id: 'addToPlaylist' },
|
||||||
{ id: 'addToFavorites' },
|
{ id: 'addToFavorites' },
|
||||||
{ divider: true, id: 'removeFromFavorites' },
|
{ divider: true, id: 'removeFromFavorites' },
|
||||||
|
@ -98,7 +105,8 @@ export const ARTIST_CONTEXT_MENU_ITEMS: SetContextMenuItems = [
|
||||||
export const PLAYLIST_CONTEXT_MENU_ITEMS: SetContextMenuItems = [
|
export const PLAYLIST_CONTEXT_MENU_ITEMS: SetContextMenuItems = [
|
||||||
{ id: 'play' },
|
{ id: 'play' },
|
||||||
{ id: 'playLast' },
|
{ id: 'playLast' },
|
||||||
{ divider: true, id: 'playNext' },
|
{ id: 'playNext' },
|
||||||
|
{ divider: true, id: 'playShuffled' },
|
||||||
{ divider: true, id: 'shareItem' },
|
{ divider: true, id: 'shareItem' },
|
||||||
{ id: 'deletePlaylist' },
|
{ id: 'deletePlaylist' },
|
||||||
];
|
];
|
||||||
|
|
|
@ -31,6 +31,7 @@ import {
|
||||||
RiInformationFill,
|
RiInformationFill,
|
||||||
RiRadio2Fill,
|
RiRadio2Fill,
|
||||||
RiDownload2Line,
|
RiDownload2Line,
|
||||||
|
RiShuffleFill,
|
||||||
} from 'react-icons/ri';
|
} from 'react-icons/ri';
|
||||||
import { AnyLibraryItems, LibraryItem, ServerType, AnyLibraryItem } from '/@/renderer/api/types';
|
import { AnyLibraryItems, LibraryItem, ServerType, AnyLibraryItem } from '/@/renderer/api/types';
|
||||||
import {
|
import {
|
||||||
|
@ -774,6 +775,12 @@ export const ContextMenuProvider = ({ children }: ContextMenuProviderProps) => {
|
||||||
leftIcon: <RiAddCircleFill size="1.1rem" />,
|
leftIcon: <RiAddCircleFill size="1.1rem" />,
|
||||||
onClick: () => handlePlay(Play.NEXT),
|
onClick: () => handlePlay(Play.NEXT),
|
||||||
},
|
},
|
||||||
|
playShuffled: {
|
||||||
|
id: 'playShuffled',
|
||||||
|
label: t('page.contextMenu.playShuffled', { postProcess: 'sentenceCase' }),
|
||||||
|
leftIcon: <RiShuffleFill size="1.1rem" />,
|
||||||
|
onClick: () => handlePlay(Play.SHUFFLE),
|
||||||
|
},
|
||||||
playSimilarSongs: {
|
playSimilarSongs: {
|
||||||
id: 'playSimilarSongs',
|
id: 'playSimilarSongs',
|
||||||
label: t('page.contextMenu.playSimilarSongs', { postProcess: 'sentenceCase' }),
|
label: t('page.contextMenu.playSimilarSongs', { postProcess: 'sentenceCase' }),
|
||||||
|
|
|
@ -23,6 +23,7 @@ export type ContextMenuItemType =
|
||||||
| 'play'
|
| 'play'
|
||||||
| 'playLast'
|
| 'playLast'
|
||||||
| 'playNext'
|
| 'playNext'
|
||||||
|
| 'playShuffled'
|
||||||
| 'addToPlaylist'
|
| 'addToPlaylist'
|
||||||
| 'removeFromPlaylist'
|
| 'removeFromPlaylist'
|
||||||
| 'addToFavorites'
|
| 'addToFavorites'
|
||||||
|
@ -45,6 +46,7 @@ export const CONFIGURABLE_CONTEXT_MENU_ITEMS: ContextMenuItemType[] = [
|
||||||
'play',
|
'play',
|
||||||
'playLast',
|
'playLast',
|
||||||
'playNext',
|
'playNext',
|
||||||
|
'playShuffled',
|
||||||
'playSimilarSongs',
|
'playSimilarSongs',
|
||||||
'addToPlaylist',
|
'addToPlaylist',
|
||||||
'removeFromPlaylist',
|
'removeFromPlaylist',
|
||||||
|
|
|
@ -215,6 +215,13 @@ export const ControlSettings = () => {
|
||||||
}),
|
}),
|
||||||
value: Play.LAST,
|
value: Play.LAST,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
label: t('setting.playButtonBehavior', {
|
||||||
|
context: 'optionPlayShuffled',
|
||||||
|
postProcess: 'titleCase',
|
||||||
|
}),
|
||||||
|
value: Play.SHUFFLE,
|
||||||
|
},
|
||||||
]}
|
]}
|
||||||
defaultValue={settings.playButtonBehavior}
|
defaultValue={settings.playButtonBehavior}
|
||||||
onChange={(e) =>
|
onChange={(e) =>
|
||||||
|
|
|
@ -107,18 +107,53 @@ export const usePlayerStore = create<PlayerSlice>()(
|
||||||
actions: {
|
actions: {
|
||||||
addToQueue: (args) => {
|
addToQueue: (args) => {
|
||||||
const { initialIndex, playType, songs } = args;
|
const { initialIndex, playType, songs } = args;
|
||||||
const { shuffledIndex } = get().current;
|
|
||||||
const shuffledQueue = get().queue.shuffled;
|
|
||||||
const songsToAddToQueue = map(songs, (song) => ({
|
const songsToAddToQueue = map(songs, (song) => ({
|
||||||
...song,
|
...song,
|
||||||
uniqueId: nanoid(),
|
uniqueId: nanoid(),
|
||||||
}));
|
}));
|
||||||
const queue = get().queue.default;
|
|
||||||
|
|
||||||
// If the queue is empty, next/last should behave the same as now
|
// If the queue is empty, next/last should behave the same as now
|
||||||
if (playType === Play.NOW || queue.length === 0) {
|
if (playType === Play.SHUFFLE) {
|
||||||
|
const songs = shuffle(songsToAddToQueue);
|
||||||
|
const initialSong = songs[0];
|
||||||
|
|
||||||
if (get().shuffle === PlayerShuffle.TRACK) {
|
if (get().shuffle === PlayerShuffle.TRACK) {
|
||||||
|
const shuffledIds = [
|
||||||
|
initialSong.uniqueId,
|
||||||
|
...shuffle(songs.slice(1).map((song) => song.uniqueId)),
|
||||||
|
];
|
||||||
|
|
||||||
|
set((state) => {
|
||||||
|
state.queue.default = songs;
|
||||||
|
state.queue.shuffled = shuffledIds;
|
||||||
|
state.current.time = 0;
|
||||||
|
state.current.player = 1;
|
||||||
|
state.current.index = 0;
|
||||||
|
state.current.shuffledIndex = 0;
|
||||||
|
state.current.song = initialSong;
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
set((state) => {
|
||||||
|
state.queue.default = songs;
|
||||||
|
state.queue.shuffled = [];
|
||||||
|
state.current.time = 0;
|
||||||
|
state.current.player = 1;
|
||||||
|
state.current.index = 0;
|
||||||
|
state.current.shuffledIndex = 0;
|
||||||
|
state.current.song = initialSong;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return get().actions.getPlayerData();
|
||||||
|
}
|
||||||
|
|
||||||
|
const shuffledQueue = get().queue.shuffled;
|
||||||
|
const queue = get().queue.default;
|
||||||
|
const { shuffledIndex } = get().current;
|
||||||
|
|
||||||
|
if (playType === Play.NOW || queue.length === 0) {
|
||||||
const index = initialIndex || 0;
|
const index = initialIndex || 0;
|
||||||
|
if (get().shuffle === PlayerShuffle.TRACK) {
|
||||||
const initialSong = songsToAddToQueue[index];
|
const initialSong = songsToAddToQueue[index];
|
||||||
const queueCopy = [...songsToAddToQueue];
|
const queueCopy = [...songsToAddToQueue];
|
||||||
|
|
||||||
|
@ -145,7 +180,6 @@ export const usePlayerStore = create<PlayerSlice>()(
|
||||||
state.current.song = initialSong;
|
state.current.song = initialSong;
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
const index = initialIndex || 0;
|
|
||||||
set((state) => {
|
set((state) => {
|
||||||
state.queue.default = songsToAddToQueue;
|
state.queue.default = songsToAddToQueue;
|
||||||
state.current.time = 0;
|
state.current.time = 0;
|
||||||
|
|
|
@ -109,6 +109,7 @@ export enum Play {
|
||||||
LAST = 'last',
|
LAST = 'last',
|
||||||
NEXT = 'next',
|
NEXT = 'next',
|
||||||
NOW = 'now',
|
NOW = 'now',
|
||||||
|
SHUFFLE = 'shuffle',
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum CrossfadeStyle {
|
export enum CrossfadeStyle {
|
||||||
|
|
Reference in a new issue