feat(queue): add go to current button

This commit is contained in:
Kendall Garner
2026-03-02 20:30:35 -08:00
parent 2854b928f6
commit f99b8ea9ee
7 changed files with 31 additions and 3 deletions
+1
View File
@@ -5,6 +5,7 @@
"addOrRemoveFromSelection": "add or remove from selection", "addOrRemoveFromSelection": "add or remove from selection",
"selectRangeOfItems": "select a range of items", "selectRangeOfItems": "select a range of items",
"clearQueue": "clear queue", "clearQueue": "clear queue",
"goToCurrent": "go to current item",
"createPlaylist": "create $t(entity.playlist, {\"count\": 1})", "createPlaylist": "create $t(entity.playlist, {\"count\": 1})",
"createRadioStation": "create $t(entity.radioStation, {\"count\": 1})", "createRadioStation": "create $t(entity.radioStation, {\"count\": 1})",
"deletePlaylist": "delete $t(entity.playlist, {\"count\": 1})", "deletePlaylist": "delete $t(entity.playlist, {\"count\": 1})",
@@ -21,6 +21,7 @@ export const DrawerPlayQueue = () => {
<PlayQueueListControls <PlayQueueListControls
handleSearch={setSearch} handleSearch={setSearch}
searchTerm={search} searchTerm={search}
tableRef={queueRef}
type={ItemListKey.SIDE_QUEUE} type={ItemListKey.SIDE_QUEUE}
/> />
</div> </div>
@@ -1,9 +1,11 @@
import { useIsFetching } from '@tanstack/react-query'; import { useIsFetching } from '@tanstack/react-query';
import { t } from 'i18next'; import { t } from 'i18next';
import { RefObject } from 'react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { queryKeys } from '/@/renderer/api/query-keys'; import { queryKeys } from '/@/renderer/api/query-keys';
import { SONG_TABLE_COLUMNS } from '/@/renderer/components/item-list/item-table-list/default-columns'; import { SONG_TABLE_COLUMNS } from '/@/renderer/components/item-list/item-table-list/default-columns';
import { ItemListHandle } from '/@/renderer/components/item-list/types';
import { usePlayer } from '/@/renderer/features/player/context/player-context'; import { usePlayer } from '/@/renderer/features/player/context/player-context';
import { useRestoreQueue, useSaveQueue } from '/@/renderer/features/player/hooks/use-queue-restore'; import { useRestoreQueue, useSaveQueue } from '/@/renderer/features/player/hooks/use-queue-restore';
import { import {
@@ -11,7 +13,7 @@ import {
SONG_DISPLAY_TYPES, SONG_DISPLAY_TYPES,
} from '/@/renderer/features/shared/components/list-config-menu'; } from '/@/renderer/features/shared/components/list-config-menu';
import { SearchInput } from '/@/renderer/features/shared/components/search-input'; import { SearchInput } from '/@/renderer/features/shared/components/search-input';
import { useCurrentServer } from '/@/renderer/store'; import { useCurrentServer, usePlayerStoreBase } from '/@/renderer/store';
import { hasFeature } from '/@/shared/api/utils'; import { hasFeature } from '/@/shared/api/utils';
import { ActionIcon } from '/@/shared/components/action-icon/action-icon'; import { ActionIcon } from '/@/shared/components/action-icon/action-icon';
import { Group } from '/@/shared/components/group/group'; import { Group } from '/@/shared/components/group/group';
@@ -21,12 +23,14 @@ import { ItemListKey, ListDisplayType } from '/@/shared/types/types';
interface PlayQueueListOptionsProps { interface PlayQueueListOptionsProps {
handleSearch: (value: string) => void; handleSearch: (value: string) => void;
searchTerm?: string; searchTerm?: string;
tableRef: RefObject<ItemListHandle | null>;
type: ItemListKey; type: ItemListKey;
} }
export const PlayQueueListControls = ({ export const PlayQueueListControls = ({
handleSearch, handleSearch,
searchTerm, searchTerm,
tableRef,
type, type,
}: PlayQueueListOptionsProps) => { }: PlayQueueListOptionsProps) => {
const { t } = useTranslation(); const { t } = useTranslation();
@@ -36,6 +40,13 @@ export const PlayQueueListControls = ({
player.clearQueue(); player.clearQueue();
}; };
const handleJumpToCurrent = () => {
const index = usePlayerStoreBase.getState().player.index;
if (index !== -1) {
tableRef.current?.scrollToIndex(index);
}
};
const handleShuffleQueue = () => { const handleShuffleQueue = () => {
player.shuffleAll(); player.shuffleAll();
}; };
@@ -58,6 +69,13 @@ export const PlayQueueListControls = ({
tooltip={{ label: t('action.clearQueue', { postProcess: 'sentenceCase' }) }} tooltip={{ label: t('action.clearQueue', { postProcess: 'sentenceCase' }) }}
variant="subtle" variant="subtle"
/> />
<ActionIcon
icon="goToItem"
iconProps={{ size: 'lg' }}
onClick={handleJumpToCurrent}
tooltip={{ label: t('action.goToCurrent', { postProcess: 'sentenceCase' }) }}
variant="subtle"
/>
</Group> </Group>
<Group gap="xs"> <Group gap="xs">
<SearchInput <SearchInput
@@ -62,6 +62,7 @@ export const PopoverPlayQueue = ({
<PlayQueueListControls <PlayQueueListControls
handleSearch={setSearch} handleSearch={setSearch}
searchTerm={search} searchTerm={search}
tableRef={queueRef}
type={ItemListKey.SIDE_QUEUE} type={ItemListKey.SIDE_QUEUE}
/> />
<PlayQueue <PlayQueue
@@ -114,6 +114,7 @@ export const SidebarPlayQueue = () => {
<PlayQueueListControls <PlayQueueListControls
handleSearch={setSearch} handleSearch={setSearch}
searchTerm={search} searchTerm={search}
tableRef={tableRef}
type={ItemListKey.SIDE_QUEUE} type={ItemListKey.SIDE_QUEUE}
/> />
<div className={styles.playQueueSection}> <div className={styles.playQueueSection}>
@@ -217,6 +218,7 @@ export const SidebarPlayQueue = () => {
<PlayQueueListControls <PlayQueueListControls
handleSearch={setSearch} handleSearch={setSearch}
searchTerm={search} searchTerm={search}
tableRef={tableRef}
type={ItemListKey.SIDE_QUEUE} type={ItemListKey.SIDE_QUEUE}
/> />
<Flex direction="column" style={{ flex: 1, minHeight: 0 }}> <Flex direction="column" style={{ flex: 1, minHeight: 0 }}>
@@ -1,5 +1,6 @@
import { useEffect, useState } from 'react'; import { useEffect, useRef, useState } from 'react';
import { ItemListHandle } from '/@/renderer/components/item-list/types';
import { NowPlayingHeader } from '/@/renderer/features/now-playing/components/now-playing-header'; import { NowPlayingHeader } from '/@/renderer/features/now-playing/components/now-playing-header';
import { PlayQueue } from '/@/renderer/features/now-playing/components/play-queue'; import { PlayQueue } from '/@/renderer/features/now-playing/components/play-queue';
import { PlayQueueListControls } from '/@/renderer/features/now-playing/components/play-queue-list-controls'; import { PlayQueueListControls } from '/@/renderer/features/now-playing/components/play-queue-list-controls';
@@ -11,6 +12,7 @@ import { ItemListKey } from '/@/shared/types/types';
const NowPlayingRoute = () => { const NowPlayingRoute = () => {
const [search, setSearch] = useState<string | undefined>(undefined); const [search, setSearch] = useState<string | undefined>(undefined);
const { setSideBar } = useAppStoreActions(); const { setSideBar } = useAppStoreActions();
const tableRef = useRef<ItemListHandle | null>(null);
useEffect(() => { useEffect(() => {
// On page enter, set rightExpanded to false // On page enter, set rightExpanded to false
@@ -28,9 +30,10 @@ const NowPlayingRoute = () => {
<PlayQueueListControls <PlayQueueListControls
handleSearch={setSearch} handleSearch={setSearch}
searchTerm={search} searchTerm={search}
tableRef={tableRef}
type={ItemListKey.QUEUE_SONG} type={ItemListKey.QUEUE_SONG}
/> />
<PlayQueue listKey={ItemListKey.QUEUE_SONG} searchTerm={search} /> <PlayQueue listKey={ItemListKey.QUEUE_SONG} ref={tableRef} searchTerm={search} />
</AnimatedPage> </AnimatedPage>
); );
}; };
+2
View File
@@ -33,6 +33,7 @@ import {
LuClipboardCopy, LuClipboardCopy,
LuClock3, LuClock3,
LuCloudDownload, LuCloudDownload,
LuCornerDownRight,
LuCornerUpRight, LuCornerUpRight,
LuDelete, LuDelete,
LuDisc, LuDisc,
@@ -183,6 +184,7 @@ export const AppIcon = {
filter: LuListFilter, filter: LuListFilter,
folder: LuFolderOpen, folder: LuFolderOpen,
genre: LuFlag, genre: LuFlag,
goToItem: LuCornerDownRight,
hash: LuHash, hash: LuHash,
home: LuSquareMenu, home: LuSquareMenu,
image: LuImage, image: LuImage,