diff --git a/src/i18n/locales/en.json b/src/i18n/locales/en.json index 90d9a92b..0a46fe4f 100644 --- a/src/i18n/locales/en.json +++ b/src/i18n/locales/en.json @@ -472,6 +472,8 @@ "discordRichPresence_description": "enable playback status in {{discord}} rich presence. Image keys are: {{icon}}, {{playing}}, and {{paused}} ", "discordUpdateInterval": "{{discord}} rich presence update interval", "discordUpdateInterval_description": "the time in seconds between each update (minimum 15 seconds)", + "doubleClickBehavior": "queue all tracks when double clicking", + "doubleClickBehavior_description": "if true, all matching tracks (e.g. album, playlist, search) will be queued. otherwise, only queue the track clicked", "enableRemote": "enable remote control server", "enableRemote_description": "enables the remote control server to allow other devices to control the application", "externalLinks": "show external links", diff --git a/src/renderer/features/player/hooks/use-handle-playqueue-add.ts b/src/renderer/features/player/hooks/use-handle-playqueue-add.ts index 7f21d246..69e586e3 100644 --- a/src/renderer/features/player/hooks/use-handle-playqueue-add.ts +++ b/src/renderer/features/player/hooks/use-handle-playqueue-add.ts @@ -1,7 +1,7 @@ import { useCallback, useRef } from 'react'; import { useQueryClient } from '@tanstack/react-query'; import { useCurrentServer, usePlayerControls, usePlayerStore } from '/@/renderer/store'; -import { usePlaybackType } from '/@/renderer/store/settings.store'; +import { useGeneralSettings, usePlaybackType } from '/@/renderer/store/settings.store'; import { PlayQueueAddOptions, Play, PlaybackType } from '/@/renderer/types'; import { toast } from '/@/renderer/components/toast/index'; import isElectron from 'is-electron'; @@ -65,6 +65,8 @@ export const useHandlePlayQueueAdd = () => { const { play } = usePlayerControls(); const timeoutIds = useRef> | null>({}); + const { doubleClickQueueAll } = useGeneralSettings(); + const handlePlayQueueAdd = useCallback( async (options: PlayQueueAddOptions) => { if (!server) return toast.error({ message: 'No server selected', type: 'error' }); @@ -121,6 +123,12 @@ export const useHandlePlayQueueAdd = () => { } else if (itemType === LibraryItem.SONG) { if (id?.length === 1) { songList = await getSongById({ id: id?.[0], queryClient, server }); + } else if (!doubleClickQueueAll && initialSongId) { + songList = await getSongById({ + id: initialSongId, + queryClient, + server, + }); } else { songList = await getSongsByQuery({ query, queryClient, server }); } @@ -195,7 +203,7 @@ export const useHandlePlayQueueAdd = () => { return null; }, - [play, playbackType, queryClient, server, t], + [doubleClickQueueAll, play, playbackType, queryClient, server, t], ); return handlePlayQueueAdd; diff --git a/src/renderer/features/settings/components/general/control-settings.tsx b/src/renderer/features/settings/components/general/control-settings.tsx index be3bb9d0..d19575ef 100644 --- a/src/renderer/features/settings/components/general/control-settings.tsx +++ b/src/renderer/features/settings/components/general/control-settings.tsx @@ -233,6 +233,28 @@ export const ControlSettings = () => { isHidden: false, title: t('setting.playButtonBehavior', { postProcess: 'sentenceCase' }), }, + { + control: ( + + setSettings({ + general: { + ...settings, + doubleClickQueueAll: e.currentTarget.checked, + }, + }) + } + /> + ), + description: t('setting.doubleClickBehavior', { + context: 'description', + postProcess: 'sentenceCase', + }), + isHidden: false, + title: t('setting.doubleClickBehavior', { postProcess: 'sentenceCase' }), + }, { control: (