reimplement playqueue list controls

This commit is contained in:
jeffvli
2025-11-13 18:48:46 -08:00
parent 498abf3c3d
commit 744780861f
6 changed files with 51 additions and 103 deletions
@@ -564,15 +564,6 @@ export const ItemGridList = ({
const imperativeHandle: ItemListHandle = useMemo(() => { const imperativeHandle: ItemListHandle = useMemo(() => {
return { return {
clearExpanded: () => {
internalState.clearExpanded();
},
clearSelected: () => {
internalState.clearSelected();
},
getItem: (index: number) => data[index],
getItemCount: () => data.length,
getItems: () => data,
internalState, internalState,
scrollToIndex: (index: number) => { scrollToIndex: (index: number) => {
scrollToIndex(index); scrollToIndex(index);
@@ -581,7 +572,7 @@ export const ItemGridList = ({
scrollToOffset(offset); scrollToOffset(offset);
}, },
}; };
}, [data, internalState, scrollToIndex, scrollToOffset]); }, [internalState, scrollToIndex, scrollToOffset]);
useEffect(() => { useEffect(() => {
handleRef.current = imperativeHandle; handleRef.current = imperativeHandle;
@@ -1276,15 +1276,6 @@ export const ItemTableList = ({
const imperativeHandle: ItemListHandle = useMemo(() => { const imperativeHandle: ItemListHandle = useMemo(() => {
return { return {
clearExpanded: () => {
internalState.clearExpanded();
},
clearSelected: () => {
internalState.clearSelected();
},
getItem: (index: number) => (enableHeader ? data[index - 1] : data[index]),
getItemCount: () => (enableHeader ? data.length : data.length),
getItems: () => data,
internalState, internalState,
scrollToIndex: (index: number) => { scrollToIndex: (index: number) => {
scrollToTableIndex(enableHeader ? index + 1 : index); scrollToTableIndex(enableHeader ? index + 1 : index);
@@ -1293,7 +1284,7 @@ export const ItemTableList = ({
scrollToTableOffset(offset); scrollToTableOffset(offset);
}, },
}; };
}, [data, enableHeader, internalState, scrollToTableIndex, scrollToTableOffset]); }, [enableHeader, internalState, scrollToTableIndex, scrollToTableOffset]);
useImperativeHandle(ref, () => imperativeHandle); useImperativeHandle(ref, () => imperativeHandle);
@@ -53,11 +53,6 @@ export interface ItemListGridComponentProps<TQuery> extends ItemListComponentPro
} }
export interface ItemListHandle { export interface ItemListHandle {
clearExpanded: () => void;
clearSelected: () => void;
getItem: (index: number) => unknown;
getItemCount: () => number;
getItems: () => unknown[];
internalState: ItemListStateActions; internalState: ItemListStateActions;
scrollToIndex: (index: number, options?: { behavior?: 'auto' | 'smooth' }) => void; scrollToIndex: (index: number, options?: { behavior?: 'auto' | 'smooth' }) => void;
scrollToOffset: (offset: number, options?: { behavior?: 'auto' | 'smooth' }) => void; scrollToOffset: (offset: number, options?: { behavior?: 'auto' | 'smooth' }) => void;
@@ -1,22 +1,22 @@
import type { AgGridReact as AgGridReactType } from '@ag-grid-community/react/lib/agGridReact';
import { type MutableRefObject } from 'react'; import { type MutableRefObject } from 'react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { ItemListHandle } from '/@/renderer/components/item-list/types';
import { SONG_TABLE_COLUMNS } from '/@/renderer/components/virtual-table'; import { SONG_TABLE_COLUMNS } from '/@/renderer/components/virtual-table';
import { usePlayerContext } from '/@/renderer/features/player/context/player-context'; import { usePlayerContext } from '/@/renderer/features/player/context/player-context';
import { updateSong } from '/@/renderer/features/player/update-remote-song'; import { updateSong } from '/@/renderer/features/player/update-remote-song';
import { ListConfigMenu } from '/@/renderer/features/shared/components/list-config-menu'; import { ListConfigMenu } from '/@/renderer/features/shared/components/list-config-menu';
import { usePlaybackType } from '/@/renderer/store/settings.store'; import { SearchInput } from '/@/renderer/features/shared/components/search-input';
import { usePlayerSong, usePlayerStoreBase } from '/@/renderer/store';
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';
import { Song } from '/@/shared/types/domain-types'; import { QueueSong } from '/@/shared/types/domain-types';
import { ItemListKey } from '/@/shared/types/types'; import { ItemListKey } from '/@/shared/types/types';
interface PlayQueueListOptionsProps { interface PlayQueueListOptionsProps {
handleSearch: (value: string) => void; handleSearch: (value: string) => void;
searchTerm?: string; searchTerm?: string;
tableRef: MutableRefObject<null | { grid: AgGridReactType<Song> }>; tableRef: MutableRefObject<ItemListHandle | null>;
type: ItemListKey; type: ItemListKey;
} }
@@ -24,94 +24,60 @@ export const PlayQueueListControls = ({
handleSearch, handleSearch,
searchTerm, searchTerm,
tableRef, tableRef,
type,
}: PlayQueueListOptionsProps) => { }: PlayQueueListOptionsProps) => {
const { t } = useTranslation(); const { t } = useTranslation();
// const {
// clearQueue,
// moveToBottomOfQueue,
// moveToNextOfQueue,
// moveToTopOfQueue,
// removeFromQueue,
// shuffleQueue,
// } = useQueueControls();
// const { pause } = usePlayerControls();
const player = usePlayerContext(); const player = usePlayerContext();
const currentSong = usePlayerSong();
const playbackType = usePlaybackType();
// const setCurrentTime = useSetCurrentTime();
const handleMoveToNext = () => { const handleMoveToNext = () => {
// const selectedRows = tableRef?.current?.grid.api.getSelectedRows(); const selectedItems = tableRef?.current?.internalState.getSelected() as
// const uniqueIds = selectedRows?.map((row) => row.uniqueId); | QueueSong[]
// if (!uniqueIds?.length) return; | undefined;
// // const playerData = moveToNextOfQueue(uniqueIds); if (!selectedItems || selectedItems.length === 0) return;
// // if (playbackType === PlaybackType.LOCAL) { player.moveSelectedToNext(selectedItems);
// // setQueueNext(playerData);
// // }
// player.moveSelectedToNext(selectedRows);
}; };
const handleMoveToBottom = () => { const handleMoveToBottom = () => {
// const selectedRows = tableRef?.current?.grid.api.getSelectedRows(); const selectedItems = tableRef?.current?.internalState.getSelected() as
// const uniqueIds = selectedRows?.map((row) => row.uniqueId); | QueueSong[]
// if (!uniqueIds?.length) return; | undefined;
// const playerData = moveToBottomOfQueue(uniqueIds); if (!selectedItems || selectedItems.length === 0) return;
// if (playbackType === PlaybackType.LOCAL) { player.moveSelectedToBottom(selectedItems);
// setQueueNext(playerData);
// }
}; };
const handleMoveToTop = () => { const handleMoveToTop = () => {
// const selectedRows = tableRef?.current?.grid.api.getSelectedRows(); const selectedItems = tableRef?.current?.internalState.getSelected() as
// const uniqueIds = selectedRows?.map((row) => row.uniqueId); | QueueSong[]
// if (!uniqueIds?.length) return; | undefined;
// const playerData = moveToTopOfQueue(uniqueIds); if (!selectedItems || selectedItems.length === 0) return;
// if (playbackType === PlaybackType.LOCAL) { player.moveSelectedToTop(selectedItems);
// setQueueNext(playerData);
// }
}; };
const handleRemoveSelected = () => { const handleRemoveSelected = () => {
// const selectedRows = tableRef?.current?.grid.api.getSelectedRows(); const selectedItems = tableRef?.current?.internalState.getSelected() as
// const uniqueIds = selectedRows?.map((row) => row.uniqueId); | QueueSong[]
// if (!uniqueIds?.length) return; | undefined;
// const currentSong = usePlayerStore.getState().current.song; if (!selectedItems || selectedItems.length === 0) return;
// const playerData = removeFromQueue(uniqueIds);
// const isCurrentSongRemoved = currentSong && uniqueIds.includes(currentSong.uniqueId); const selectedUniqueIds = selectedItems.map((item) => item._uniqueId);
// if (playbackType === PlaybackType.LOCAL) { const isCurrentSongRemoved =
// if (isCurrentSongRemoved) { currentSong && selectedUniqueIds.includes(currentSong._uniqueId);
// setQueue(playerData);
// } else { player.clearSelected(selectedItems);
// setQueueNext(playerData);
// } if (isCurrentSongRemoved) {
// } // Get the new current song after removal
// if (isCurrentSongRemoved) { const newCurrentSong = usePlayerStoreBase.getState().getCurrentSong();
// updateSong(playerData.current.song); updateSong(newCurrentSong);
// } }
}; };
const handleClearQueue = () => { const handleClearQueue = () => {
// const playerData = clearQueue();
// if (playbackType === PlaybackType.LOCAL) {
// setQueue(playerData);
// mpvPlayer!.pause();
// }
player.clearQueue(); player.clearQueue();
// setCurrentTime(0);
// pause();
}; };
const handleShuffleQueue = () => { const handleShuffleQueue = () => {
// const playerData = shuffleQueue(); player.shuffleAll();
// if (playbackType === PlaybackType.LOCAL) {
// setQueueNext(playerData);
// }
}; };
return ( return (
@@ -165,7 +131,12 @@ export const PlayQueueListControls = ({
variant="subtle" variant="subtle"
/> />
</Group> </Group>
<Group> <Group gap="xs">
<SearchInput
enableHotkey={false}
onChange={(e) => handleSearch(e.target.value)}
value={searchTerm}
/>
<ListConfigMenu <ListConfigMenu
listKey={ItemListKey.SIDE_QUEUE} listKey={ItemListKey.SIDE_QUEUE}
tableColumnsData={SONG_TABLE_COLUMNS} tableColumnsData={SONG_TABLE_COLUMNS}
@@ -1,10 +1,9 @@
import type { Ref } from 'react';
import { nanoid } from 'nanoid/non-secure'; import { nanoid } from 'nanoid/non-secure';
import { forwardRef, useEffect, useMemo, useRef } from 'react'; import { forwardRef, useEffect, useMemo, useRef } from 'react';
import { ItemTableList } from '/@/renderer/components/item-list/item-table-list/item-table-list'; import { ItemTableList } from '/@/renderer/components/item-list/item-table-list/item-table-list';
import { ItemTableListColumn } from '/@/renderer/components/item-list/item-table-list/item-table-list-column'; import { ItemTableListColumn } from '/@/renderer/components/item-list/item-table-list/item-table-list-column';
import { ItemListHandle } from '/@/renderer/components/item-list/types';
import { import {
useIsPlayerFetching, useIsPlayerFetching,
usePlayerContext, usePlayerContext,
@@ -24,7 +23,7 @@ type QueueProps = {
searchTerm: string | undefined; searchTerm: string | undefined;
}; };
export const PlayQueue = forwardRef(({ listKey, searchTerm }: QueueProps, ref: Ref<any>) => { export const PlayQueue = forwardRef<ItemListHandle, QueueProps>(({ listKey, searchTerm }, ref) => {
const { table } = useListSettings(listKey) || {}; const { table } = useListSettings(listKey) || {};
const queue = usePlayerQueue(); const queue = usePlayerQueue();
@@ -1,12 +1,13 @@
import { useRef, useState } from 'react'; import { useRef, useState } from 'react';
import { ItemListHandle } from '/@/renderer/components/item-list/types';
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';
import { Stack } from '/@/shared/components/stack/stack'; import { Stack } from '/@/shared/components/stack/stack';
import { ItemListKey } from '/@/shared/types/types'; import { ItemListKey } from '/@/shared/types/types';
export const SidebarPlayQueue = () => { export const SidebarPlayQueue = () => {
const tableRef = useRef<null>(null); const tableRef = useRef<ItemListHandle | null>(null);
const [search, setSearch] = useState<string | undefined>(undefined); const [search, setSearch] = useState<string | undefined>(undefined);
return ( return (
@@ -17,7 +18,7 @@ export const SidebarPlayQueue = () => {
tableRef={tableRef} tableRef={tableRef}
type={ItemListKey.SIDE_QUEUE} type={ItemListKey.SIDE_QUEUE}
/> />
<PlayQueue listKey={ItemListKey.SIDE_QUEUE} searchTerm={search} /> <PlayQueue listKey={ItemListKey.SIDE_QUEUE} ref={tableRef} searchTerm={search} />
</Stack> </Stack>
); );
}; };