mirror of
https://github.com/antebudimir/feishin.git
synced 2026-01-01 18:33:33 +00:00
Lint all files
This commit is contained in:
parent
22af76b4d6
commit
30e52ebb54
334 changed files with 76519 additions and 75932 deletions
|
|
@ -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>
|
||||
);
|
||||
});
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue