Lint all files

This commit is contained in:
jeffvli 2023-07-01 19:10:05 -07:00
parent 22af76b4d6
commit 30e52ebb54
334 changed files with 76519 additions and 75932 deletions

View file

@ -6,32 +6,32 @@ import { Song } from '/@/renderer/api/types';
import { PlayQueue } from '/@/renderer/features/now-playing/components/play-queue';
export const DrawerPlayQueue = () => {
const queueRef = useRef<{ grid: AgGridReactType<Song> } | null>(null);
const queueRef = useRef<{ grid: AgGridReactType<Song> } | null>(null);
return (
<Flex
direction="column"
h="100%"
>
<Box
bg="var(--main-bg)"
sx={{ borderRadius: '10px' }}
>
<PlayQueueListControls
tableRef={queueRef}
type="sideQueue"
/>
</Box>
<Flex
bg="var(--main-bg)"
h="100%"
mb="0.6rem"
>
<PlayQueue
ref={queueRef}
type="sideQueue"
/>
</Flex>
</Flex>
);
return (
<Flex
direction="column"
h="100%"
>
<Box
bg="var(--main-bg)"
sx={{ borderRadius: '10px' }}
>
<PlayQueueListControls
tableRef={queueRef}
type="sideQueue"
/>
</Box>
<Flex
bg="var(--main-bg)"
h="100%"
mb="0.6rem"
>
<PlayQueue
ref={queueRef}
type="sideQueue"
/>
</Flex>
</Flex>
);
};

View file

@ -2,14 +2,14 @@ import { PageHeader } from '/@/renderer/components';
import { LibraryHeaderBar } from '/@/renderer/features/shared';
export const NowPlayingHeader = () => {
// const currentSong = useCurrentSong();
// const theme = useTheme();
// const currentSong = useCurrentSong();
// const theme = useTheme();
return (
<PageHeader backgroundColor="var(--titlebar-bg)">
<LibraryHeaderBar>
<LibraryHeaderBar.Title>Queue</LibraryHeaderBar.Title>
</LibraryHeaderBar>
</PageHeader>
);
return (
<PageHeader backgroundColor="var(--titlebar-bg)">
<LibraryHeaderBar>
<LibraryHeaderBar.Title>Queue</LibraryHeaderBar.Title>
</LibraryHeaderBar>
</PageHeader>
);
};

View file

@ -4,12 +4,12 @@ import { Group } from '@mantine/core';
import { Button, Popover } from '/@/renderer/components';
import isElectron from 'is-electron';
import {
RiArrowDownLine,
RiArrowUpLine,
RiShuffleLine,
RiDeleteBinLine,
RiListSettingsLine,
RiEraserLine,
RiArrowDownLine,
RiArrowUpLine,
RiShuffleLine,
RiDeleteBinLine,
RiListSettingsLine,
RiEraserLine,
} from 'react-icons/ri';
import { Song } from '/@/renderer/api/types';
import { usePlayerControls, useQueueControls } from '/@/renderer/store';
@ -21,156 +21,156 @@ import { TableConfigDropdown } from '/@/renderer/components/virtual-table';
const mpvPlayer = isElectron() ? window.electron.mpvPlayer : null;
interface PlayQueueListOptionsProps {
tableRef: MutableRefObject<{ grid: AgGridReactType<Song> } | null>;
type: TableType;
tableRef: MutableRefObject<{ grid: AgGridReactType<Song> } | null>;
type: TableType;
}
export const PlayQueueListControls = ({ type, tableRef }: PlayQueueListOptionsProps) => {
const { clearQueue, moveToBottomOfQueue, moveToTopOfQueue, shuffleQueue, removeFromQueue } =
useQueueControls();
const { clearQueue, moveToBottomOfQueue, moveToTopOfQueue, shuffleQueue, removeFromQueue } =
useQueueControls();
const { pause } = usePlayerControls();
const { pause } = usePlayerControls();
const playerType = usePlayerType();
const setCurrentTime = useSetCurrentTime();
const playerType = usePlayerType();
const setCurrentTime = useSetCurrentTime();
const handleMoveToBottom = () => {
const selectedRows = tableRef?.current?.grid.api.getSelectedRows();
const uniqueIds = selectedRows?.map((row) => row.uniqueId);
if (!uniqueIds?.length) return;
const handleMoveToBottom = () => {
const selectedRows = tableRef?.current?.grid.api.getSelectedRows();
const uniqueIds = selectedRows?.map((row) => row.uniqueId);
if (!uniqueIds?.length) return;
const playerData = moveToBottomOfQueue(uniqueIds);
const playerData = moveToBottomOfQueue(uniqueIds);
if (playerType === PlaybackType.LOCAL) {
mpvPlayer.setQueueNext(playerData);
}
};
if (playerType === PlaybackType.LOCAL) {
mpvPlayer.setQueueNext(playerData);
}
};
const handleMoveToTop = () => {
const selectedRows = tableRef?.current?.grid.api.getSelectedRows();
const uniqueIds = selectedRows?.map((row) => row.uniqueId);
if (!uniqueIds?.length) return;
const handleMoveToTop = () => {
const selectedRows = tableRef?.current?.grid.api.getSelectedRows();
const uniqueIds = selectedRows?.map((row) => row.uniqueId);
if (!uniqueIds?.length) return;
const playerData = moveToTopOfQueue(uniqueIds);
const playerData = moveToTopOfQueue(uniqueIds);
if (playerType === PlaybackType.LOCAL) {
mpvPlayer.setQueueNext(playerData);
}
};
if (playerType === PlaybackType.LOCAL) {
mpvPlayer.setQueueNext(playerData);
}
};
const handleRemoveSelected = () => {
const selectedRows = tableRef?.current?.grid.api.getSelectedRows();
const uniqueIds = selectedRows?.map((row) => row.uniqueId);
if (!uniqueIds?.length) return;
const handleRemoveSelected = () => {
const selectedRows = tableRef?.current?.grid.api.getSelectedRows();
const uniqueIds = selectedRows?.map((row) => row.uniqueId);
if (!uniqueIds?.length) return;
const currentSong = usePlayerStore.getState().current.song;
const playerData = removeFromQueue(uniqueIds);
const isCurrentSongRemoved = currentSong && uniqueIds.includes(currentSong.uniqueId);
const currentSong = usePlayerStore.getState().current.song;
const playerData = removeFromQueue(uniqueIds);
const isCurrentSongRemoved = currentSong && uniqueIds.includes(currentSong.uniqueId);
if (playerType === PlaybackType.LOCAL) {
if (isCurrentSongRemoved) {
mpvPlayer.setQueue(playerData);
} else {
mpvPlayer.setQueueNext(playerData);
}
}
};
if (playerType === PlaybackType.LOCAL) {
if (isCurrentSongRemoved) {
mpvPlayer.setQueue(playerData);
} else {
mpvPlayer.setQueueNext(playerData);
}
}
};
const handleClearQueue = () => {
const playerData = clearQueue();
const handleClearQueue = () => {
const playerData = clearQueue();
if (playerType === PlaybackType.LOCAL) {
mpvPlayer.setQueue(playerData);
mpvPlayer.pause();
}
if (playerType === PlaybackType.LOCAL) {
mpvPlayer.setQueue(playerData);
mpvPlayer.pause();
}
setCurrentTime(0);
pause();
};
setCurrentTime(0);
pause();
};
const handleShuffleQueue = () => {
const playerData = shuffleQueue();
const handleShuffleQueue = () => {
const playerData = shuffleQueue();
if (playerType === PlaybackType.LOCAL) {
mpvPlayer.setQueueNext(playerData);
}
};
if (playerType === PlaybackType.LOCAL) {
mpvPlayer.setQueueNext(playerData);
}
};
return (
<Group
position="apart"
px="1rem"
py="1rem"
sx={{ alignItems: 'center' }}
w="100%"
>
<Group spacing="sm">
<Button
compact
size="md"
tooltip={{ label: 'Shuffle queue' }}
variant="default"
onClick={handleShuffleQueue}
return (
<Group
position="apart"
px="1rem"
py="1rem"
sx={{ alignItems: 'center' }}
w="100%"
>
<RiShuffleLine size="1.1rem" />
</Button>
<Button
compact
size="md"
tooltip={{ label: 'Move selected to bottom' }}
variant="default"
onClick={handleMoveToBottom}
>
<RiArrowDownLine size="1.1rem" />
</Button>
<Button
compact
size="md"
tooltip={{ label: 'Move selected to top' }}
variant="default"
onClick={handleMoveToTop}
>
<RiArrowUpLine size="1.1rem" />
</Button>
<Button
compact
size="md"
tooltip={{ label: 'Remove selected' }}
variant="default"
onClick={handleRemoveSelected}
>
<RiEraserLine size="1.1rem" />
</Button>
<Button
compact
size="md"
tooltip={{ label: 'Clear queue' }}
variant="default"
onClick={handleClearQueue}
>
<RiDeleteBinLine size="1.1rem" />
</Button>
</Group>
<Group>
<Popover
position="top-end"
transitionProps={{ transition: 'fade' }}
>
<Popover.Target>
<Button
compact
size="md"
tooltip={{ label: 'Configure' }}
variant="subtle"
>
<RiListSettingsLine size="1.1rem" />
</Button>
</Popover.Target>
<Popover.Dropdown>
<TableConfigDropdown type={type} />
</Popover.Dropdown>
</Popover>
</Group>
</Group>
);
<Group spacing="sm">
<Button
compact
size="md"
tooltip={{ label: 'Shuffle queue' }}
variant="default"
onClick={handleShuffleQueue}
>
<RiShuffleLine size="1.1rem" />
</Button>
<Button
compact
size="md"
tooltip={{ label: 'Move selected to bottom' }}
variant="default"
onClick={handleMoveToBottom}
>
<RiArrowDownLine size="1.1rem" />
</Button>
<Button
compact
size="md"
tooltip={{ label: 'Move selected to top' }}
variant="default"
onClick={handleMoveToTop}
>
<RiArrowUpLine size="1.1rem" />
</Button>
<Button
compact
size="md"
tooltip={{ label: 'Remove selected' }}
variant="default"
onClick={handleRemoveSelected}
>
<RiEraserLine size="1.1rem" />
</Button>
<Button
compact
size="md"
tooltip={{ label: 'Clear queue' }}
variant="default"
onClick={handleClearQueue}
>
<RiDeleteBinLine size="1.1rem" />
</Button>
</Group>
<Group>
<Popover
position="top-end"
transitionProps={{ transition: 'fade' }}
>
<Popover.Target>
<Button
compact
size="md"
tooltip={{ label: 'Configure' }}
variant="subtle"
>
<RiListSettingsLine size="1.1rem" />
</Button>
</Popover.Target>
<Popover.Dropdown>
<TableConfigDropdown type={type} />
</Popover.Dropdown>
</Popover>
</Group>
</Group>
);
};

View file

@ -1,26 +1,26 @@
import type { Ref } from 'react';
import { useState, forwardRef, useEffect, useImperativeHandle, useMemo, useRef } from 'react';
import type {
CellDoubleClickedEvent,
RowClassRules,
RowDragEvent,
RowNode,
CellDoubleClickedEvent,
RowClassRules,
RowDragEvent,
RowNode,
} from '@ag-grid-community/core';
import type { AgGridReact as AgGridReactType } from '@ag-grid-community/react/lib/agGridReact';
import '@ag-grid-community/styles/ag-theme-alpine.css';
import {
useAppStoreActions,
useCurrentSong,
useDefaultQueue,
usePlayerControls,
usePreviousSong,
useQueueControls,
useAppStoreActions,
useCurrentSong,
useDefaultQueue,
usePlayerControls,
usePreviousSong,
useQueueControls,
} from '/@/renderer/store';
import {
usePlayerType,
useSettingsStore,
useSettingsStoreActions,
useTableSettings,
usePlayerType,
useSettingsStore,
useSettingsStoreActions,
useTableSettings,
} from '/@/renderer/store/settings.store';
import { useMergedRef } from '@mantine/hooks';
import isElectron from 'is-electron';
@ -39,194 +39,200 @@ const utils = isElectron() ? window.electron.utils : null;
const mpris = isElectron() && utils?.isLinux() ? window.electron.mpris : null;
type QueueProps = {
type: TableType;
type: TableType;
};
export const PlayQueue = forwardRef(({ type }: QueueProps, ref: Ref<any>) => {
const tableRef = useRef<AgGridReactType | null>(null);
const mergedRef = useMergedRef(ref, tableRef);
const queue = useDefaultQueue();
const { reorderQueue, setCurrentTrack } = useQueueControls();
const currentSong = useCurrentSong();
const previousSong = usePreviousSong();
const { setSettings } = useSettingsStoreActions();
const { setAppStore } = useAppStoreActions();
const tableConfig = useTableSettings(type);
const [gridApi, setGridApi] = useState<AgGridReactType | undefined>();
const playerType = usePlayerType();
const { play } = usePlayerControls();
const tableRef = useRef<AgGridReactType | null>(null);
const mergedRef = useMergedRef(ref, tableRef);
const queue = useDefaultQueue();
const { reorderQueue, setCurrentTrack } = useQueueControls();
const currentSong = useCurrentSong();
const previousSong = usePreviousSong();
const { setSettings } = useSettingsStoreActions();
const { setAppStore } = useAppStoreActions();
const tableConfig = useTableSettings(type);
const [gridApi, setGridApi] = useState<AgGridReactType | undefined>();
const playerType = usePlayerType();
const { play } = usePlayerControls();
useEffect(() => {
if (tableRef.current) {
setGridApi(tableRef.current);
}
}, []);
useImperativeHandle(ref, () => ({
get grid() {
return gridApi;
},
}));
const columnDefs = useMemo(() => getColumnDefs(tableConfig.columns), [tableConfig.columns]);
const handleDoubleClick = (e: CellDoubleClickedEvent) => {
const playerData = setCurrentTrack(e.data.uniqueId);
mpris?.updateSong({
currentTime: 0,
song: playerData.current.song,
status: 'Playing',
});
if (playerType === PlaybackType.LOCAL) {
mpvPlayer.setQueue(playerData);
mpvPlayer.play();
}
play();
};
const handleDragStart = () => {
if (type === 'sideDrawerQueue') {
setAppStore({ isReorderingQueue: true });
}
};
let timeout: any;
const handleDragEnd = (e: RowDragEvent<QueueSong>) => {
if (!e.nodes.length) return;
const selectedUniqueIds = e.nodes
.map((node) => node.data?.uniqueId)
.filter((e) => e !== undefined);
const playerData = reorderQueue(selectedUniqueIds as string[], e.overNode?.data?.uniqueId);
if (playerType === PlaybackType.LOCAL) {
mpvPlayer.setQueueNext(playerData);
}
if (type === 'sideDrawerQueue') {
setAppStore({ isReorderingQueue: false });
}
const { api } = tableRef?.current || {};
clearTimeout(timeout);
timeout = setTimeout(() => api?.redrawRows(), 250);
};
const handleGridReady = () => {
const { api } = tableRef?.current || {};
if (currentSong?.uniqueId) {
const currentNode = api?.getRowNode(currentSong?.uniqueId);
if (!currentNode) return;
api?.ensureNodeVisible(currentNode, 'middle');
}
};
const handleColumnChange = () => {
const { columnApi } = tableRef?.current || {};
const columnsOrder = columnApi?.getAllGridColumns();
if (!columnsOrder) return;
const columnsInSettings = useSettingsStore.getState().tables[type].columns;
const updatedColumns = [];
for (const column of columnsOrder) {
const columnInSettings = columnsInSettings.find((c) => c.column === column.getColDef().colId);
if (columnInSettings) {
updatedColumns.push({
...columnInSettings,
...(!useSettingsStore.getState().tables[type].autoFit && {
width: column.getActualWidth(),
}),
});
}
}
setSettings({
tables: {
...useSettingsStore.getState().tables,
[type]: {
...useSettingsStore.getState().tables[type],
columns: updatedColumns,
},
},
});
};
const debouncedColumnChange = debounce(handleColumnChange, 250);
const handleGridSizeChange = () => {
if (tableConfig.autoFit) {
tableRef?.current?.api.sizeColumnsToFit();
}
};
const rowClassRules = useMemo<RowClassRules | undefined>(() => {
return {
'current-song': (params) => {
return params.data.uniqueId === currentSong?.uniqueId;
},
};
}, [currentSong?.uniqueId]);
// Redraw the current song row when the previous song changes
useEffect(() => {
if (tableRef?.current) {
const { api, columnApi } = tableRef?.current || {};
if (api == null || columnApi == null) {
return;
}
const currentNode = currentSong?.uniqueId ? api.getRowNode(currentSong.uniqueId) : undefined;
const previousNode = previousSong?.uniqueId
? api.getRowNode(previousSong?.uniqueId)
: undefined;
const rowNodes = [currentNode, previousNode].filter((e) => e !== undefined) as RowNode<any>[];
if (rowNodes) {
api.redrawRows({ rowNodes });
if (tableConfig.followCurrentSong) {
if (!currentNode) return;
api.ensureNodeVisible(currentNode, 'middle');
useEffect(() => {
if (tableRef.current) {
setGridApi(tableRef.current);
}
}
}
}, [currentSong, previousSong, tableConfig.followCurrentSong]);
}, []);
const handleContextMenu = useHandleTableContextMenu(LibraryItem.SONG, QUEUE_CONTEXT_MENU_ITEMS);
useImperativeHandle(ref, () => ({
get grid() {
return gridApi;
},
}));
return (
<ErrorBoundary FallbackComponent={ErrorFallback}>
<VirtualGridAutoSizerContainer>
<VirtualTable
ref={mergedRef}
alwaysShowHorizontalScroll
rowDragEntireRow
rowDragMultiRow
autoFitColumns={tableConfig.autoFit}
columnDefs={columnDefs}
deselectOnClickOutside={type === 'fullScreen'}
getRowId={(data) => data.data.uniqueId}
rowBuffer={50}
rowClassRules={rowClassRules}
rowData={queue}
rowHeight={tableConfig.rowHeight || 40}
suppressCellFocus={type === 'fullScreen'}
onCellContextMenu={handleContextMenu}
onCellDoubleClicked={handleDoubleClick}
onColumnMoved={handleColumnChange}
onColumnResized={debouncedColumnChange}
onDragStarted={handleDragStart}
onGridReady={handleGridReady}
onGridSizeChanged={handleGridSizeChange}
onRowDragEnd={handleDragEnd}
/>
</VirtualGridAutoSizerContainer>
</ErrorBoundary>
);
const columnDefs = useMemo(() => getColumnDefs(tableConfig.columns), [tableConfig.columns]);
const handleDoubleClick = (e: CellDoubleClickedEvent) => {
const playerData = setCurrentTrack(e.data.uniqueId);
mpris?.updateSong({
currentTime: 0,
song: playerData.current.song,
status: 'Playing',
});
if (playerType === PlaybackType.LOCAL) {
mpvPlayer.setQueue(playerData);
mpvPlayer.play();
}
play();
};
const handleDragStart = () => {
if (type === 'sideDrawerQueue') {
setAppStore({ isReorderingQueue: true });
}
};
let timeout: any;
const handleDragEnd = (e: RowDragEvent<QueueSong>) => {
if (!e.nodes.length) return;
const selectedUniqueIds = e.nodes
.map((node) => node.data?.uniqueId)
.filter((e) => e !== undefined);
const playerData = reorderQueue(selectedUniqueIds as string[], e.overNode?.data?.uniqueId);
if (playerType === PlaybackType.LOCAL) {
mpvPlayer.setQueueNext(playerData);
}
if (type === 'sideDrawerQueue') {
setAppStore({ isReorderingQueue: false });
}
const { api } = tableRef?.current || {};
clearTimeout(timeout);
timeout = setTimeout(() => api?.redrawRows(), 250);
};
const handleGridReady = () => {
const { api } = tableRef?.current || {};
if (currentSong?.uniqueId) {
const currentNode = api?.getRowNode(currentSong?.uniqueId);
if (!currentNode) return;
api?.ensureNodeVisible(currentNode, 'middle');
}
};
const handleColumnChange = () => {
const { columnApi } = tableRef?.current || {};
const columnsOrder = columnApi?.getAllGridColumns();
if (!columnsOrder) return;
const columnsInSettings = useSettingsStore.getState().tables[type].columns;
const updatedColumns = [];
for (const column of columnsOrder) {
const columnInSettings = columnsInSettings.find(
(c) => c.column === column.getColDef().colId,
);
if (columnInSettings) {
updatedColumns.push({
...columnInSettings,
...(!useSettingsStore.getState().tables[type].autoFit && {
width: column.getActualWidth(),
}),
});
}
}
setSettings({
tables: {
...useSettingsStore.getState().tables,
[type]: {
...useSettingsStore.getState().tables[type],
columns: updatedColumns,
},
},
});
};
const debouncedColumnChange = debounce(handleColumnChange, 250);
const handleGridSizeChange = () => {
if (tableConfig.autoFit) {
tableRef?.current?.api.sizeColumnsToFit();
}
};
const rowClassRules = useMemo<RowClassRules | undefined>(() => {
return {
'current-song': (params) => {
return params.data.uniqueId === currentSong?.uniqueId;
},
};
}, [currentSong?.uniqueId]);
// Redraw the current song row when the previous song changes
useEffect(() => {
if (tableRef?.current) {
const { api, columnApi } = tableRef?.current || {};
if (api == null || columnApi == null) {
return;
}
const currentNode = currentSong?.uniqueId
? api.getRowNode(currentSong.uniqueId)
: undefined;
const previousNode = previousSong?.uniqueId
? api.getRowNode(previousSong?.uniqueId)
: undefined;
const rowNodes = [currentNode, previousNode].filter(
(e) => e !== undefined,
) as RowNode<any>[];
if (rowNodes) {
api.redrawRows({ rowNodes });
if (tableConfig.followCurrentSong) {
if (!currentNode) return;
api.ensureNodeVisible(currentNode, 'middle');
}
}
}
}, [currentSong, previousSong, tableConfig.followCurrentSong]);
const handleContextMenu = useHandleTableContextMenu(LibraryItem.SONG, QUEUE_CONTEXT_MENU_ITEMS);
return (
<ErrorBoundary FallbackComponent={ErrorFallback}>
<VirtualGridAutoSizerContainer>
<VirtualTable
ref={mergedRef}
alwaysShowHorizontalScroll
rowDragEntireRow
rowDragMultiRow
autoFitColumns={tableConfig.autoFit}
columnDefs={columnDefs}
deselectOnClickOutside={type === 'fullScreen'}
getRowId={(data) => data.data.uniqueId}
rowBuffer={50}
rowClassRules={rowClassRules}
rowData={queue}
rowHeight={tableConfig.rowHeight || 40}
suppressCellFocus={type === 'fullScreen'}
onCellContextMenu={handleContextMenu}
onCellDoubleClicked={handleDoubleClick}
onColumnMoved={handleColumnChange}
onColumnResized={debouncedColumnChange}
onDragStarted={handleDragStart}
onGridReady={handleGridReady}
onGridSizeChanged={handleGridSizeChange}
onRowDragEnd={handleDragEnd}
/>
</VirtualGridAutoSizerContainer>
</ErrorBoundary>
);
});

View file

@ -10,30 +10,30 @@ import { Platform } from '/@/renderer/types';
import { VirtualGridContainer } from '/@/renderer/components/virtual-grid';
export const SidebarPlayQueue = () => {
const queueRef = useRef<{ grid: AgGridReactType<Song> } | null>(null);
const { windowBarStyle } = useWindowSettings();
const queueRef = useRef<{ grid: AgGridReactType<Song> } | null>(null);
const { windowBarStyle } = useWindowSettings();
const isWeb = windowBarStyle === Platform.WEB;
return (
<VirtualGridContainer>
{isWeb && (
<Stack mr={isWeb ? '130px' : undefined}>
<PageHeader backgroundColor="var(--titlebar-bg)" />
</Stack>
)}
<Paper
display={!isWeb ? 'flex' : undefined}
h={!isWeb ? '65px' : undefined}
>
<PlayQueueListControls
tableRef={queueRef}
type="sideQueue"
/>
</Paper>
<PlayQueue
ref={queueRef}
type="sideQueue"
/>
</VirtualGridContainer>
);
const isWeb = windowBarStyle === Platform.WEB;
return (
<VirtualGridContainer>
{isWeb && (
<Stack mr={isWeb ? '130px' : undefined}>
<PageHeader backgroundColor="var(--titlebar-bg)" />
</Stack>
)}
<Paper
display={!isWeb ? 'flex' : undefined}
h={!isWeb ? '65px' : undefined}
>
<PlayQueueListControls
tableRef={queueRef}
type="sideQueue"
/>
</Paper>
<PlayQueue
ref={queueRef}
type="sideQueue"
/>
</VirtualGridContainer>
);
};