mirror of
https://github.com/antebudimir/feishin.git
synced 2026-01-02 10:53:33 +00:00
restructure files onto electron-vite boilerplate
This commit is contained in:
parent
91ce2cd8a1
commit
1cf587bc8f
457 changed files with 9927 additions and 11705 deletions
|
|
@ -1,19 +1,21 @@
|
|||
import type { ICellRendererParams } from '@ag-grid-community/core';
|
||||
|
||||
import { RiMoreFill } from 'react-icons/ri';
|
||||
|
||||
import { Button } from '/@/renderer/components/button';
|
||||
import { CellContainer } from '/@/renderer/components/virtual-table/cells/generic-cell';
|
||||
|
||||
export const ActionsCell = ({ context, api }: ICellRendererParams) => {
|
||||
export const ActionsCell = ({ api, context }: ICellRendererParams) => {
|
||||
return (
|
||||
<CellContainer $position="center">
|
||||
<Button
|
||||
compact
|
||||
variant="subtle"
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
context.onCellContextMenu(undefined, api, e);
|
||||
}}
|
||||
variant="subtle"
|
||||
>
|
||||
<RiMoreFill />
|
||||
</Button>
|
||||
|
|
|
|||
|
|
@ -1,15 +1,17 @@
|
|||
import React from 'react';
|
||||
import type { AlbumArtist, Artist } from '/@/renderer/api/types';
|
||||
import type { ICellRendererParams } from '@ag-grid-community/core';
|
||||
|
||||
import React from 'react';
|
||||
import { generatePath } from 'react-router';
|
||||
import { Link } from 'react-router-dom';
|
||||
import type { AlbumArtist, Artist } from '/@/renderer/api/types';
|
||||
|
||||
import { Separator } from '/@/renderer/components/separator';
|
||||
import { Skeleton } from '/@/renderer/components/skeleton';
|
||||
import { Text } from '/@/renderer/components/text';
|
||||
import { CellContainer } from '/@/renderer/components/virtual-table/cells/generic-cell';
|
||||
import { AppRoute } from '/@/renderer/router/routes';
|
||||
import { Skeleton } from '/@/renderer/components/skeleton';
|
||||
import { Separator } from '/@/renderer/components/separator';
|
||||
|
||||
export const AlbumArtistCell = ({ value, data }: ICellRendererParams) => {
|
||||
export const AlbumArtistCell = ({ data, value }: ICellRendererParams) => {
|
||||
if (value === undefined) {
|
||||
return (
|
||||
<CellContainer $position="left">
|
||||
|
|
@ -28,7 +30,7 @@ export const AlbumArtistCell = ({ value, data }: ICellRendererParams) => {
|
|||
overflow="hidden"
|
||||
size="md"
|
||||
>
|
||||
{value?.map((item: Artist | AlbumArtist, index: number) => (
|
||||
{value?.map((item: AlbumArtist | Artist, index: number) => (
|
||||
<React.Fragment key={`row-${item.id}-${data.uniqueId}`}>
|
||||
{index > 0 && <Separator />}
|
||||
{item.id ? (
|
||||
|
|
|
|||
|
|
@ -1,15 +1,17 @@
|
|||
import React from 'react';
|
||||
import type { AlbumArtist, Artist } from '/@/renderer/api/types';
|
||||
import type { ICellRendererParams } from '@ag-grid-community/core';
|
||||
|
||||
import React from 'react';
|
||||
import { generatePath } from 'react-router';
|
||||
import { Link } from 'react-router-dom';
|
||||
import type { AlbumArtist, Artist } from '/@/renderer/api/types';
|
||||
|
||||
import { Separator } from '/@/renderer/components/separator';
|
||||
import { Skeleton } from '/@/renderer/components/skeleton';
|
||||
import { Text } from '/@/renderer/components/text';
|
||||
import { CellContainer } from '/@/renderer/components/virtual-table/cells/generic-cell';
|
||||
import { AppRoute } from '/@/renderer/router/routes';
|
||||
import { Skeleton } from '/@/renderer/components/skeleton';
|
||||
import { Separator } from '/@/renderer/components/separator';
|
||||
|
||||
export const ArtistCell = ({ value, data }: ICellRendererParams) => {
|
||||
export const ArtistCell = ({ data, value }: ICellRendererParams) => {
|
||||
if (value === undefined) {
|
||||
return (
|
||||
<CellContainer $position="left">
|
||||
|
|
@ -28,7 +30,7 @@ export const ArtistCell = ({ value, data }: ICellRendererParams) => {
|
|||
overflow="hidden"
|
||||
size="md"
|
||||
>
|
||||
{value?.map((item: Artist | AlbumArtist, index: number) => (
|
||||
{value?.map((item: AlbumArtist | Artist, index: number) => (
|
||||
<React.Fragment key={`row-${item.id}-${data.uniqueId}`}>
|
||||
{index > 0 && <Separator />}
|
||||
{item.id ? (
|
||||
|
|
|
|||
|
|
@ -1,13 +1,15 @@
|
|||
import React, { MouseEvent } from 'react';
|
||||
import type { UnstyledButtonProps } from '@mantine/core';
|
||||
|
||||
import React, { MouseEvent } from 'react';
|
||||
import { RiPlayFill } from 'react-icons/ri';
|
||||
import styled from 'styled-components';
|
||||
import { Play } from '/@/renderer/types';
|
||||
import { usePlayButtonBehavior } from '/@/renderer/store/settings.store';
|
||||
|
||||
import { LibraryItem } from '/@/renderer/api/types';
|
||||
import { usePlayQueueAdd } from '/@/renderer/features/player';
|
||||
import { usePlayButtonBehavior } from '/@/renderer/store/settings.store';
|
||||
import { Play } from '/@/renderer/types';
|
||||
|
||||
type PlayButtonType = UnstyledButtonProps & React.ComponentPropsWithoutRef<'button'>;
|
||||
type PlayButtonType = React.ComponentPropsWithoutRef<'button'> & UnstyledButtonProps;
|
||||
|
||||
const PlayButton = styled.button<PlayButtonType>`
|
||||
position: absolute;
|
||||
|
|
@ -50,9 +52,9 @@ const ListConverControlsContainer = styled.div`
|
|||
`;
|
||||
|
||||
export const ListCoverControls = ({
|
||||
context,
|
||||
itemData,
|
||||
itemType,
|
||||
context,
|
||||
uniqueId,
|
||||
}: {
|
||||
context: Record<string, any>;
|
||||
|
|
|
|||
|
|
@ -1,18 +1,20 @@
|
|||
import React, { useMemo } from 'react';
|
||||
import type { ICellRendererParams } from '@ag-grid-community/core';
|
||||
|
||||
import { Center } from '@mantine/core';
|
||||
import { motion } from 'framer-motion';
|
||||
import React, { useMemo } from 'react';
|
||||
import { RiAlbumFill } from 'react-icons/ri';
|
||||
import { generatePath } from 'react-router';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { SimpleImg } from 'react-simple-img';
|
||||
import styled from 'styled-components';
|
||||
|
||||
import { AlbumArtist, Artist } from '/@/renderer/api/types';
|
||||
import { Text } from '/@/renderer/components/text';
|
||||
import { AppRoute } from '/@/renderer/router/routes';
|
||||
import { Skeleton } from '/@/renderer/components/skeleton';
|
||||
import { SEPARATOR_STRING } from '/@/renderer/api/utils';
|
||||
import { Skeleton } from '/@/renderer/components/skeleton';
|
||||
import { Text } from '/@/renderer/components/text';
|
||||
import { ListCoverControls } from '/@/renderer/components/virtual-table/cells/combined-title-cell-controls';
|
||||
import { AppRoute } from '/@/renderer/router/routes';
|
||||
|
||||
const CellContainer = styled(motion.div)<{ height: number }>`
|
||||
display: grid;
|
||||
|
|
@ -61,11 +63,11 @@ const StyledImage = styled(SimpleImg)`
|
|||
`;
|
||||
|
||||
export const CombinedTitleCell = ({
|
||||
value,
|
||||
rowIndex,
|
||||
node,
|
||||
context,
|
||||
data,
|
||||
node,
|
||||
rowIndex,
|
||||
value,
|
||||
}: ICellRendererParams) => {
|
||||
const artists = useMemo(() => {
|
||||
if (!value) return null;
|
||||
|
|
@ -141,7 +143,7 @@ export const CombinedTitleCell = ({
|
|||
size="md"
|
||||
>
|
||||
{artists?.length ? (
|
||||
artists.map((artist: Artist | AlbumArtist, index: number) => (
|
||||
artists.map((artist: AlbumArtist | Artist, index: number) => (
|
||||
<React.Fragment key={`queue-${rowIndex}-artist-${artist.id}`}>
|
||||
{index > 0 ? SEPARATOR_STRING : null}
|
||||
{artist.id ? (
|
||||
|
|
|
|||
|
|
@ -1,11 +1,13 @@
|
|||
/* eslint-disable import/no-cycle */
|
||||
import type { ICellRendererParams } from '@ag-grid-community/core';
|
||||
|
||||
import { RiHeartFill, RiHeartLine } from 'react-icons/ri';
|
||||
|
||||
import { Button } from '/@/renderer/components/button';
|
||||
import { CellContainer } from '/@/renderer/components/virtual-table/cells/generic-cell';
|
||||
import { useCreateFavorite, useDeleteFavorite } from '/@/renderer/features/shared';
|
||||
|
||||
export const FavoriteCell = ({ value, data, node }: ICellRendererParams) => {
|
||||
export const FavoriteCell = ({ data, node, value }: ICellRendererParams) => {
|
||||
const createMutation = useCreateFavorite({});
|
||||
const deleteMutation = useDeleteFavorite({});
|
||||
|
||||
|
|
@ -49,6 +51,7 @@ export const FavoriteCell = ({ value, data, node }: ICellRendererParams) => {
|
|||
<CellContainer $position="center">
|
||||
<Button
|
||||
compact
|
||||
onClick={handleToggleFavorite}
|
||||
sx={{
|
||||
svg: {
|
||||
fill: !value
|
||||
|
|
@ -57,7 +60,6 @@ export const FavoriteCell = ({ value, data, node }: ICellRendererParams) => {
|
|||
},
|
||||
}}
|
||||
variant="subtle"
|
||||
onClick={handleToggleFavorite}
|
||||
>
|
||||
{!value ? <RiHeartLine size="1.3em" /> : <RiHeartFill size="1.3em" />}
|
||||
</Button>
|
||||
|
|
|
|||
|
|
@ -1,11 +1,13 @@
|
|||
import { useState } from 'react';
|
||||
import { ICellRendererParams } from '@ag-grid-community/core';
|
||||
import { Group } from '@mantine/core';
|
||||
import { useState } from 'react';
|
||||
import { RiCheckboxBlankLine, RiCheckboxLine } from 'react-icons/ri';
|
||||
import styled from 'styled-components';
|
||||
|
||||
import { getNodesByDiscNumber, setNodeSelection } from '../utils';
|
||||
|
||||
import { Button } from '/@/renderer/components/button';
|
||||
import { Paper } from '/@/renderer/components/paper';
|
||||
import { getNodesByDiscNumber, setNodeSelection } from '../utils';
|
||||
|
||||
const Container = styled(Paper)`
|
||||
display: flex;
|
||||
|
|
@ -14,7 +16,7 @@ const Container = styled(Paper)`
|
|||
border: 1px solid transparent;
|
||||
`;
|
||||
|
||||
export const FullWidthDiscCell = ({ node, data, api }: ICellRendererParams) => {
|
||||
export const FullWidthDiscCell = ({ api, data, node }: ICellRendererParams) => {
|
||||
const [isSelected, setIsSelected] = useState(false);
|
||||
|
||||
const handleToggleDiscNodes = () => {
|
||||
|
|
@ -38,9 +40,9 @@ export const FullWidthDiscCell = ({ node, data, api }: ICellRendererParams) => {
|
|||
<Button
|
||||
compact
|
||||
leftIcon={isSelected ? <RiCheckboxLine /> : <RiCheckboxBlankLine />}
|
||||
onClick={handleToggleDiscNodes}
|
||||
size="md"
|
||||
variant="subtle"
|
||||
onClick={handleToggleDiscNodes}
|
||||
>
|
||||
{data.name}
|
||||
</Button>
|
||||
|
|
|
|||
|
|
@ -1,10 +1,12 @@
|
|||
import type { ICellRendererParams } from '@ag-grid-community/core';
|
||||
|
||||
import { Link } from 'react-router-dom';
|
||||
import styled from 'styled-components';
|
||||
|
||||
import { Skeleton } from '/@/renderer/components/skeleton';
|
||||
import { Text } from '/@/renderer/components/text';
|
||||
|
||||
export const CellContainer = styled.div<{ $position?: 'left' | 'center' | 'right' }>`
|
||||
export const CellContainer = styled.div<{ $position?: 'center' | 'left' | 'right' }>`
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: ${(props) =>
|
||||
|
|
@ -22,13 +24,13 @@ type Options = {
|
|||
array?: boolean;
|
||||
isArray?: boolean;
|
||||
isLink?: boolean;
|
||||
position?: 'left' | 'center' | 'right';
|
||||
position?: 'center' | 'left' | 'right';
|
||||
primary?: boolean;
|
||||
};
|
||||
|
||||
export const GenericCell = (
|
||||
{ value, valueFormatted }: ICellRendererParams,
|
||||
{ position, primary, isLink }: Options,
|
||||
{ isLink, position, primary }: Options,
|
||||
) => {
|
||||
const displayedValue = valueFormatted || value;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,13 +1,15 @@
|
|||
import React from 'react';
|
||||
import type { ICellRendererParams } from '@ag-grid-community/core';
|
||||
import { generatePath, Link } from 'react-router-dom';
|
||||
import type { AlbumArtist, Artist } from '/@/renderer/api/types';
|
||||
import type { ICellRendererParams } from '@ag-grid-community/core';
|
||||
|
||||
import React from 'react';
|
||||
import { generatePath, Link } from 'react-router-dom';
|
||||
|
||||
import { Separator } from '/@/renderer/components/separator';
|
||||
import { Text } from '/@/renderer/components/text';
|
||||
import { CellContainer } from '/@/renderer/components/virtual-table/cells/generic-cell';
|
||||
import { Separator } from '/@/renderer/components/separator';
|
||||
import { useGenreRoute } from '/@/renderer/hooks/use-genre-route';
|
||||
|
||||
export const GenreCell = ({ value, data }: ICellRendererParams) => {
|
||||
export const GenreCell = ({ data, value }: ICellRendererParams) => {
|
||||
const genrePath = useGenreRoute();
|
||||
return (
|
||||
<CellContainer $position="left">
|
||||
|
|
@ -16,7 +18,7 @@ export const GenreCell = ({ value, data }: ICellRendererParams) => {
|
|||
overflow="hidden"
|
||||
size="md"
|
||||
>
|
||||
{value?.map((item: Artist | AlbumArtist, index: number) => (
|
||||
{value?.map((item: AlbumArtist | Artist, index: number) => (
|
||||
<React.Fragment key={`row-${item.id}-${data.uniqueId}`}>
|
||||
{index > 0 && <Separator />}
|
||||
<Text
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
import type { ICellRendererParams } from '@ag-grid-community/core';
|
||||
import { Skeleton } from '/@/renderer/components/skeleton';
|
||||
import { CellContainer } from '/@/renderer/components/virtual-table/cells/generic-cell';
|
||||
|
||||
import { useMemo } from 'react';
|
||||
|
||||
import { Skeleton } from '/@/renderer/components/skeleton';
|
||||
import { Text } from '/@/renderer/components/text';
|
||||
import { CellContainer } from '/@/renderer/components/virtual-table/cells/generic-cell';
|
||||
import { replaceURLWithHTMLLinks } from '/@/renderer/utils/linkify';
|
||||
|
||||
export const NoteCell = ({ value }: ICellRendererParams) => {
|
||||
|
|
|
|||
|
|
@ -1,10 +1,11 @@
|
|||
/* eslint-disable import/no-cycle */
|
||||
import type { ICellRendererParams } from '@ag-grid-community/core';
|
||||
|
||||
import { Rating } from '/@/renderer/components/rating';
|
||||
import { CellContainer } from '/@/renderer/components/virtual-table/cells/generic-cell';
|
||||
import { useSetRating } from '/@/renderer/features/shared';
|
||||
|
||||
export const RatingCell = ({ value, node }: ICellRendererParams) => {
|
||||
export const RatingCell = ({ node, value }: ICellRendererParams) => {
|
||||
const updateRatingMutation = useSetRating({});
|
||||
|
||||
const handleUpdateRating = (rating: number) => {
|
||||
|
|
@ -27,9 +28,9 @@ export const RatingCell = ({ value, node }: ICellRendererParams) => {
|
|||
return (
|
||||
<CellContainer $position="center">
|
||||
<Rating
|
||||
onChange={handleUpdateRating}
|
||||
size="xs"
|
||||
value={value?.userRating}
|
||||
onChange={handleUpdateRating}
|
||||
/>
|
||||
</CellContainer>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import type { ICellRendererParams } from '@ag-grid-community/core';
|
||||
|
||||
import { Text } from '/@/renderer/components/text';
|
||||
import { CellContainer } from '/@/renderer/components/virtual-table/cells/generic-cell';
|
||||
|
||||
|
|
@ -132,7 +133,7 @@ const StaticSvg = () => {
|
|||
);
|
||||
};
|
||||
|
||||
export const RowIndexCell = ({ value, eGridCell }: ICellRendererParams) => {
|
||||
export const RowIndexCell = ({ eGridCell, value }: ICellRendererParams) => {
|
||||
const classList = eGridCell.classList;
|
||||
// const isFocused = classList.contains('focused');
|
||||
const isPlaying = classList.contains('playing');
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import type { ICellRendererParams } from '@ag-grid-community/core';
|
||||
|
||||
import { Skeleton } from '/@/renderer/components/skeleton';
|
||||
import { Text } from '/@/renderer/components/text';
|
||||
import { CellContainer } from '/@/renderer/components/virtual-table/cells/generic-cell';
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import type { IHeaderParams } from '@ag-grid-community/core';
|
||||
|
||||
import { FiClock } from 'react-icons/fi';
|
||||
|
||||
export interface ICustomHeaderParams extends IHeaderParams {
|
||||
|
|
|
|||
|
|
@ -1,19 +1,21 @@
|
|||
import type { ReactNode } from 'react';
|
||||
import type { IHeaderParams } from '@ag-grid-community/core';
|
||||
import type { ReactNode } from 'react';
|
||||
|
||||
import { AiOutlineNumber } from 'react-icons/ai';
|
||||
import { FiClock } from 'react-icons/fi';
|
||||
import { RiHeartLine, RiMoreFill, RiStarLine } from 'react-icons/ri';
|
||||
import styled from 'styled-components';
|
||||
import { _Text } from '/@/renderer/components/text';
|
||||
|
||||
type Presets = 'duration' | 'rowIndex' | 'userFavorite' | 'userRating' | 'actions';
|
||||
import { _Text } from '/@/renderer/components/text';
|
||||
|
||||
type Options = {
|
||||
children?: ReactNode;
|
||||
position?: 'left' | 'center' | 'right';
|
||||
position?: 'center' | 'left' | 'right';
|
||||
preset?: Presets;
|
||||
};
|
||||
|
||||
type Presets = 'actions' | 'duration' | 'rowIndex' | 'userFavorite' | 'userRating';
|
||||
|
||||
export const HeaderWrapper = styled.div<{ $position: Options['position'] }>`
|
||||
display: flex;
|
||||
justify-content: ${(props) =>
|
||||
|
|
@ -77,7 +79,7 @@ const headerPresets = {
|
|||
|
||||
export const GenericTableHeader = (
|
||||
{ displayName }: IHeaderParams,
|
||||
{ preset, children, position }: Options,
|
||||
{ children, position, preset }: Options,
|
||||
) => {
|
||||
if (preset) {
|
||||
return <HeaderWrapper $position={position}>{headerPresets[preset]}</HeaderWrapper>;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import { MutableRefObject } from 'react';
|
||||
import type { AgGridReact as AgGridReactType } from '@ag-grid-community/react/lib/agGridReact';
|
||||
|
||||
import { useClickOutside } from '@mantine/hooks';
|
||||
import { MutableRefObject } from 'react';
|
||||
|
||||
export const useClickOutsideDeselect = (tableRef: MutableRefObject<AgGridReactType | null>) => {
|
||||
const handleDeselect = () => {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
import { MutableRefObject, useEffect, useMemo, useRef } from 'react';
|
||||
import { RowClassRules, RowNode } from '@ag-grid-community/core';
|
||||
import type { AgGridReact as AgGridReactType } from '@ag-grid-community/react/lib/agGridReact';
|
||||
|
||||
import { RowClassRules, RowNode } from '@ag-grid-community/core';
|
||||
import { MutableRefObject, useEffect, useMemo, useRef } from 'react';
|
||||
|
||||
import { Song } from '/@/renderer/api/types';
|
||||
import { useAppFocus } from '/@/renderer/hooks';
|
||||
import { useCurrentSong, usePlayerStore } from '/@/renderer/store';
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import { useInView } from 'framer-motion';
|
||||
import { useEffect, useRef } from 'react';
|
||||
|
||||
import { useWindowSettings } from '/@/renderer/store/settings.store';
|
||||
import { Platform } from '/@/renderer/types';
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import { MutableRefObject, useCallback, useMemo } from 'react';
|
||||
import type { AgGridReact as AgGridReactType } from '@ag-grid-community/react/lib/agGridReact';
|
||||
|
||||
import {
|
||||
BodyScrollEvent,
|
||||
ColDef,
|
||||
|
|
@ -8,13 +9,17 @@ import {
|
|||
PaginationChangedEvent,
|
||||
RowDoubleClickedEvent,
|
||||
} from '@ag-grid-community/core';
|
||||
import type { AgGridReact as AgGridReactType } from '@ag-grid-community/react/lib/agGridReact';
|
||||
import { QueryKey, useQueryClient } from '@tanstack/react-query';
|
||||
import debounce from 'lodash/debounce';
|
||||
import orderBy from 'lodash/orderBy';
|
||||
import { MutableRefObject, useCallback, useMemo } from 'react';
|
||||
import { generatePath, useNavigate } from 'react-router';
|
||||
import { useSearchParams } from 'react-router-dom';
|
||||
|
||||
import { ListKey, useListStoreByKey } from '../../../store/list.store';
|
||||
|
||||
import { api } from '/@/renderer/api';
|
||||
import { QueryPagination, queryKeys } from '/@/renderer/api/query-keys';
|
||||
import { queryKeys, QueryPagination } from '/@/renderer/api/query-keys';
|
||||
import {
|
||||
BasePaginatedResponse,
|
||||
BaseQuery,
|
||||
|
|
@ -26,8 +31,6 @@ import { SetContextMenuItems, useHandleTableContextMenu } from '/@/renderer/feat
|
|||
import { AppRoute } from '/@/renderer/router/routes';
|
||||
import { useListStoreActions } from '/@/renderer/store';
|
||||
import { ListDisplayType, TablePagination } from '/@/renderer/types';
|
||||
import { useSearchParams } from 'react-router-dom';
|
||||
import { ListKey, useListStoreByKey } from '../../../store/list.store';
|
||||
|
||||
export type AgGridFetchFn<TResponse, TFilter> = (
|
||||
args: { filter: TFilter; limit: number; startIndex: number },
|
||||
|
|
@ -44,24 +47,24 @@ interface UseAgGridProps<TFilter> {
|
|||
itemCount?: number;
|
||||
itemType: LibraryItem;
|
||||
pageKey: string;
|
||||
server: ServerListItem | null;
|
||||
server: null | ServerListItem;
|
||||
tableRef: MutableRefObject<AgGridReactType | null>;
|
||||
}
|
||||
|
||||
const BLOCK_SIZE = 500;
|
||||
|
||||
export const useVirtualTable = <TFilter extends BaseQuery<any>>({
|
||||
server,
|
||||
tableRef,
|
||||
pageKey,
|
||||
itemType,
|
||||
columnType,
|
||||
contextMenu,
|
||||
itemCount,
|
||||
customFilters,
|
||||
isSearchParams,
|
||||
isClientSide,
|
||||
isClientSideSort,
|
||||
columnType,
|
||||
isSearchParams,
|
||||
itemCount,
|
||||
itemType,
|
||||
pageKey,
|
||||
server,
|
||||
tableRef,
|
||||
}: UseAgGridProps<TFilter>) => {
|
||||
const queryClient = useQueryClient();
|
||||
const navigate = useNavigate();
|
||||
|
|
|
|||
|
|
@ -1,30 +1,42 @@
|
|||
import { Ref, forwardRef, useRef, useEffect, useCallback, useMemo } from 'react';
|
||||
import type {
|
||||
ICellRendererParams,
|
||||
ValueGetterParams,
|
||||
IHeaderParams,
|
||||
ValueFormatterParams,
|
||||
ColDef,
|
||||
ColumnMovedEvent,
|
||||
NewColumnsLoadedEvent,
|
||||
GridReadyEvent,
|
||||
GridSizeChangedEvent,
|
||||
ICellRendererParams,
|
||||
IHeaderParams,
|
||||
ModelUpdatedEvent,
|
||||
NewColumnsLoadedEvent,
|
||||
ValueFormatterParams,
|
||||
ValueGetterParams,
|
||||
} from '@ag-grid-community/core';
|
||||
import type { AgGridReactProps } from '@ag-grid-community/react';
|
||||
import { AgGridReact } from '@ag-grid-community/react';
|
||||
import type { AgGridReact as AgGridReactType } from '@ag-grid-community/react/lib/agGridReact';
|
||||
|
||||
import { AgGridReact } from '@ag-grid-community/react';
|
||||
import { useClickOutside, useMergedRef } from '@mantine/hooks';
|
||||
import formatDuration from 'format-duration';
|
||||
import { AnimatePresence } from 'framer-motion';
|
||||
import { forwardRef, Ref, useCallback, useEffect, useMemo, useRef } from 'react';
|
||||
import { generatePath } from 'react-router';
|
||||
import styled from 'styled-components';
|
||||
|
||||
import i18n from '/@/i18n/i18n';
|
||||
import { ActionsCell } from '/@/renderer/components/virtual-table/cells/actions-cell';
|
||||
import { AlbumArtistCell } from '/@/renderer/components/virtual-table/cells/album-artist-cell';
|
||||
import { ArtistCell } from '/@/renderer/components/virtual-table/cells/artist-cell';
|
||||
import { CombinedTitleCell } from '/@/renderer/components/virtual-table/cells/combined-title-cell';
|
||||
import { FavoriteCell } from '/@/renderer/components/virtual-table/cells/favorite-cell';
|
||||
import { GenericCell } from '/@/renderer/components/virtual-table/cells/generic-cell';
|
||||
import { GenreCell } from '/@/renderer/components/virtual-table/cells/genre-cell';
|
||||
import { NoteCell } from '/@/renderer/components/virtual-table/cells/note-cell';
|
||||
import { RatingCell } from '/@/renderer/components/virtual-table/cells/rating-cell';
|
||||
import { RowIndexCell } from '/@/renderer/components/virtual-table/cells/row-index-cell';
|
||||
import { TitleCell } from '/@/renderer/components/virtual-table/cells/title-cell';
|
||||
import { GenericTableHeader } from '/@/renderer/components/virtual-table/headers/generic-table-header';
|
||||
import { useFixedTableHeader } from '/@/renderer/components/virtual-table/hooks/use-fixed-table-header';
|
||||
import { TablePagination } from '/@/renderer/components/virtual-table/table-pagination';
|
||||
import { useTableChange } from '/@/renderer/hooks/use-song-change';
|
||||
import { AppRoute } from '/@/renderer/router/routes';
|
||||
import { PersistedTableColumn } from '/@/renderer/store/settings.store';
|
||||
import {
|
||||
|
|
@ -32,27 +44,17 @@ import {
|
|||
TableColumn,
|
||||
TablePagination as TablePaginationType,
|
||||
} from '/@/renderer/types';
|
||||
import { FavoriteCell } from '/@/renderer/components/virtual-table/cells/favorite-cell';
|
||||
import { RatingCell } from '/@/renderer/components/virtual-table/cells/rating-cell';
|
||||
import { TablePagination } from '/@/renderer/components/virtual-table/table-pagination';
|
||||
import { ActionsCell } from '/@/renderer/components/virtual-table/cells/actions-cell';
|
||||
import { TitleCell } from '/@/renderer/components/virtual-table/cells/title-cell';
|
||||
import { useFixedTableHeader } from '/@/renderer/components/virtual-table/hooks/use-fixed-table-header';
|
||||
import { NoteCell } from '/@/renderer/components/virtual-table/cells/note-cell';
|
||||
import { RowIndexCell } from '/@/renderer/components/virtual-table/cells/row-index-cell';
|
||||
import i18n from '/@/i18n/i18n';
|
||||
import {
|
||||
formatDateAbsolute,
|
||||
formatDateAbsoluteUTC,
|
||||
formatDateRelative,
|
||||
formatSizeString,
|
||||
} from '/@/renderer/utils/format';
|
||||
import { useTableChange } from '/@/renderer/hooks/use-song-change';
|
||||
|
||||
export * from './hooks/use-click-outside-deselect';
|
||||
export * from './hooks/use-fixed-table-header';
|
||||
export * from './table-config-dropdown';
|
||||
export * from './table-pagination';
|
||||
export * from './hooks/use-fixed-table-header';
|
||||
export * from './hooks/use-click-outside-deselect';
|
||||
export * from './utils';
|
||||
|
||||
const TableWrapper = styled.div`
|
||||
|
|
@ -491,16 +493,16 @@ export const VirtualTable = forwardRef(
|
|||
(
|
||||
{
|
||||
autoFitColumns,
|
||||
deselectOnClickOutside,
|
||||
autoHeight,
|
||||
stickyHeader,
|
||||
transparentHeader,
|
||||
deselectOnClickOutside,
|
||||
onColumnMoved,
|
||||
onNewColumnsLoaded,
|
||||
onGridReady,
|
||||
onGridSizeChanged,
|
||||
onNewColumnsLoaded,
|
||||
paginationProps,
|
||||
shouldUpdateSong,
|
||||
stickyHeader,
|
||||
transparentHeader,
|
||||
...rest
|
||||
}: VirtualTableProps,
|
||||
ref: Ref<AgGridReactType | null>,
|
||||
|
|
@ -584,7 +586,7 @@ export const VirtualTable = forwardRef(
|
|||
[autoFitColumns],
|
||||
);
|
||||
|
||||
const { tableHeaderRef, tableContainerRef } = useFixedTableHeader({
|
||||
const { tableContainerRef, tableHeaderRef } = useFixedTableHeader({
|
||||
enabled: stickyHeader || false,
|
||||
});
|
||||
|
||||
|
|
@ -592,32 +594,32 @@ export const VirtualTable = forwardRef(
|
|||
|
||||
return (
|
||||
<TableWrapper
|
||||
ref={mergedWrapperRef}
|
||||
className={
|
||||
transparentHeader
|
||||
? 'ag-theme-alpine-dark ag-header-transparent'
|
||||
: 'ag-theme-alpine-dark'
|
||||
}
|
||||
ref={mergedWrapperRef}
|
||||
>
|
||||
<DummyHeader ref={tableHeaderRef} />
|
||||
<AgGridReact
|
||||
ref={mergedRef}
|
||||
animateRows
|
||||
maintainColumnOrder
|
||||
suppressAsyncEvents
|
||||
suppressContextMenu
|
||||
suppressCopyRowsToClipboard
|
||||
suppressMoveWhenRowDragging
|
||||
suppressPaginationPanel
|
||||
suppressScrollOnNewData
|
||||
blockLoadDebounceMillis={200}
|
||||
cacheBlockSize={300}
|
||||
cacheOverflowSize={1}
|
||||
defaultColDef={defaultColumnDefs}
|
||||
enableCellChangeFlash={false}
|
||||
headerHeight={36}
|
||||
maintainColumnOrder
|
||||
ref={mergedRef}
|
||||
rowBuffer={30}
|
||||
rowSelection="multiple"
|
||||
suppressAsyncEvents
|
||||
suppressContextMenu
|
||||
suppressCopyRowsToClipboard
|
||||
suppressMoveWhenRowDragging
|
||||
suppressPaginationPanel
|
||||
suppressScrollOnNewData
|
||||
{...rest}
|
||||
onColumnMoved={handleColumnMoved}
|
||||
onGridReady={handleGridReady}
|
||||
|
|
@ -627,9 +629,9 @@ export const VirtualTable = forwardRef(
|
|||
/>
|
||||
{paginationProps && (
|
||||
<AnimatePresence
|
||||
presenceAffectsLayout
|
||||
initial={false}
|
||||
mode="wait"
|
||||
presenceAffectsLayout
|
||||
>
|
||||
<TablePagination
|
||||
{...paginationProps}
|
||||
|
|
|
|||
|
|
@ -1,12 +1,14 @@
|
|||
import type { ChangeEvent } from 'react';
|
||||
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import i18n from '/@/i18n/i18n';
|
||||
import { Option } from '/@/renderer/components/option';
|
||||
import { MultiSelect } from '/@/renderer/components/select';
|
||||
import { Slider } from '/@/renderer/components/slider';
|
||||
import { Switch } from '/@/renderer/components/switch';
|
||||
import { useSettingsStoreActions, useSettingsStore } from '/@/renderer/store/settings.store';
|
||||
import { useSettingsStore, useSettingsStoreActions } from '/@/renderer/store/settings.store';
|
||||
import { TableColumn, TableType } from '/@/renderer/types';
|
||||
import { Option } from '/@/renderer/components/option';
|
||||
import i18n from '/@/i18n/i18n';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
export const SONG_TABLE_COLUMNS = [
|
||||
{
|
||||
|
|
@ -408,8 +410,8 @@ export const TableConfigDropdown = ({ type }: TableConfigDropdownProps) => {
|
|||
label={(value) => `Item size: ${value}`}
|
||||
max={100}
|
||||
min={25}
|
||||
w="100%"
|
||||
onChangeEnd={handleUpdateRowHeight}
|
||||
w="100%"
|
||||
/>
|
||||
</Option.Control>
|
||||
</Option>
|
||||
|
|
@ -420,8 +422,8 @@ export const TableConfigDropdown = ({ type }: TableConfigDropdownProps) => {
|
|||
data={SONG_TABLE_COLUMNS}
|
||||
defaultValue={tableConfig[type]?.columns.map((column) => column.column)}
|
||||
dropdownPosition="bottom"
|
||||
width={300}
|
||||
onChange={handleAddOrRemoveColumns}
|
||||
width={300}
|
||||
/>
|
||||
</Option.Control>
|
||||
</Option>
|
||||
|
|
|
|||
|
|
@ -1,19 +1,22 @@
|
|||
import { MutableRefObject } from 'react';
|
||||
import type { AgGridReact as AgGridReactType } from '@ag-grid-community/react/lib/agGridReact';
|
||||
|
||||
import { Group } from '@mantine/core';
|
||||
import { useForm } from '@mantine/form';
|
||||
import { useDisclosure } from '@mantine/hooks';
|
||||
import { MutableRefObject } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { RiHashtag } from 'react-icons/ri';
|
||||
import { Button } from '/@/renderer/components/button';
|
||||
|
||||
import { MotionFlex } from '../motion';
|
||||
|
||||
import { Button } from '/@/renderer/components/button';
|
||||
import { NumberInput } from '/@/renderer/components/input';
|
||||
import { Pagination } from '/@/renderer/components/pagination';
|
||||
import { Popover } from '/@/renderer/components/popover';
|
||||
import { Text } from '/@/renderer/components/text';
|
||||
import { useContainerQuery } from '/@/renderer/hooks';
|
||||
import { TablePagination as TablePaginationType } from '/@/renderer/types';
|
||||
import { ListKey } from '/@/renderer/store';
|
||||
import { TablePagination as TablePaginationType } from '/@/renderer/types';
|
||||
|
||||
interface TablePaginationProps {
|
||||
pageKey: ListKey;
|
||||
|
|
@ -25,10 +28,10 @@ interface TablePaginationProps {
|
|||
|
||||
export const TablePagination = ({
|
||||
pageKey,
|
||||
tableRef,
|
||||
pagination,
|
||||
setPagination,
|
||||
setIdPagination,
|
||||
setPagination,
|
||||
tableRef,
|
||||
}: TablePaginationProps) => {
|
||||
const { t } = useTranslation();
|
||||
const [isGoToPageOpen, handlers] = useDisclosure(false);
|
||||
|
|
@ -70,14 +73,14 @@ export const TablePagination = ({
|
|||
|
||||
return (
|
||||
<MotionFlex
|
||||
ref={containerQuery.ref}
|
||||
layout
|
||||
align="center"
|
||||
animate={{ y: 0 }}
|
||||
exit={{ y: 50 }}
|
||||
initial={{ y: 50 }}
|
||||
justify="space-between"
|
||||
layout
|
||||
p="1rem"
|
||||
ref={containerQuery.ref}
|
||||
sx={{ borderTop: '1px solid var(--generic-border-color)' }}
|
||||
>
|
||||
<Text
|
||||
|
|
@ -102,18 +105,19 @@ export const TablePagination = ({
|
|||
)}
|
||||
</Text>
|
||||
<Group
|
||||
ref={containerQuery.ref}
|
||||
noWrap
|
||||
ref={containerQuery.ref}
|
||||
spacing="sm"
|
||||
>
|
||||
<Popover
|
||||
trapFocus
|
||||
onClose={() => handlers.close()}
|
||||
opened={isGoToPageOpen}
|
||||
position="bottom-start"
|
||||
onClose={() => handlers.close()}
|
||||
trapFocus
|
||||
>
|
||||
<Popover.Target>
|
||||
<Button
|
||||
onClick={() => handlers.toggle()}
|
||||
radius="sm"
|
||||
size="sm"
|
||||
sx={{ height: '26px', padding: '0', width: '26px' }}
|
||||
|
|
@ -121,7 +125,6 @@ export const TablePagination = ({
|
|||
label: t('action.goToPage', { postProcess: 'sentenceCase' }),
|
||||
}}
|
||||
variant="default"
|
||||
onClick={() => handlers.toggle()}
|
||||
>
|
||||
<RiHashtag size={15} />
|
||||
</Button>
|
||||
|
|
@ -147,14 +150,14 @@ export const TablePagination = ({
|
|||
</Popover.Dropdown>
|
||||
</Popover>
|
||||
<Pagination
|
||||
noWrap
|
||||
$hideDividers={!containerQuery.isSm}
|
||||
boundaries={1}
|
||||
noWrap
|
||||
onChange={handlePagination}
|
||||
radius="sm"
|
||||
siblings={containerQuery.isMd ? 2 : containerQuery.isSm ? 1 : 0}
|
||||
total={pagination.totalPages - 1}
|
||||
value={pagination.currentPage + 1}
|
||||
onChange={handlePagination}
|
||||
/>
|
||||
</Group>
|
||||
</MotionFlex>
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import { GridApi, RowNode } from '@ag-grid-community/core';
|
|||
export const getNodesByDiscNumber = (args: {
|
||||
api: GridApi;
|
||||
discNumber: number;
|
||||
subtitle: string | null;
|
||||
subtitle: null | string;
|
||||
}) => {
|
||||
const { api, discNumber, subtitle } = args;
|
||||
|
||||
|
|
@ -21,7 +21,7 @@ export const setNodeSelection = (args: {
|
|||
isSelected: boolean;
|
||||
nodes: RowNode<any>[];
|
||||
}) => {
|
||||
const { nodes, isSelected } = args;
|
||||
const { isSelected, nodes } = args;
|
||||
|
||||
nodes.forEach((node) => {
|
||||
node.setSelected(isSelected);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue