restructure files onto electron-vite boilerplate

This commit is contained in:
jeffvli 2025-05-18 14:03:18 -07:00
parent 91ce2cd8a1
commit 1cf587bc8f
457 changed files with 9927 additions and 11705 deletions

View file

@ -1,5 +1,7 @@
import type { AgGridReact as AgGridReactType } from '@ag-grid-community/react/lib/agGridReact';
import { lazy, MutableRefObject, Suspense } from 'react';
import { Spinner } from '/@/renderer/components';
import { VirtualInfiniteGridRef } from '/@/renderer/components/virtual-grid';
import { useListContext } from '/@/renderer/context/list-context';
@ -19,12 +21,12 @@ const GenreListTableView = lazy(() =>
);
interface AlbumListContentProps {
gridRef: MutableRefObject<VirtualInfiniteGridRef | null>;
gridRef: MutableRefObject<null | VirtualInfiniteGridRef>;
itemCount?: number;
tableRef: MutableRefObject<AgGridReactType | null>;
}
export const GenreListContent = ({ itemCount, gridRef, tableRef }: AlbumListContentProps) => {
export const GenreListContent = ({ gridRef, itemCount, tableRef }: AlbumListContentProps) => {
const { pageKey } = useListContext();
const { display } = useListStoreByKey({ key: pageKey });

View file

@ -3,6 +3,7 @@ import { useCallback, useMemo } from 'react';
import { useSearchParams } from 'react-router-dom';
import AutoSizer, { Size } from 'react-virtualized-auto-sizer';
import { ListOnScrollProps } from 'react-window';
import { api } from '/@/renderer/api';
import { queryKeys } from '/@/renderer/api/query-keys';
import { Album, GenreListQuery, GenreListResponse, LibraryItem } from '/@/renderer/api/types';
@ -13,16 +14,16 @@ import {
} from '/@/renderer/components/virtual-grid';
import { useListContext } from '/@/renderer/context/list-context';
import { usePlayQueueAdd } from '/@/renderer/features/player';
import { useGenreRoute } from '/@/renderer/hooks/use-genre-route';
import { useCurrentServer, useListStoreActions, useListStoreByKey } from '/@/renderer/store';
import { CardRow, ListDisplayType } from '/@/renderer/types';
import { useGenreRoute } from '/@/renderer/hooks/use-genre-route';
export const GenreListGridView = ({ gridRef, itemCount }: any) => {
const queryClient = useQueryClient();
const server = useCurrentServer();
const handlePlayQueueAdd = usePlayQueueAdd();
const { pageKey, id } = useListContext();
const { grid, display, filter } = useListStoreByKey<GenreListQuery>({ key: pageKey });
const { id, pageKey } = useListContext();
const { display, filter, grid } = useListStoreByKey<GenreListQuery>({ key: pageKey });
const { setGrid } = useListStoreActions();
const genrePath = useGenreRoute();
@ -53,7 +54,7 @@ export const GenreListGridView = ({ gridRef, itemCount }: any) => {
);
const fetchInitialData = useCallback(() => {
const query: Omit<GenreListQuery, 'startIndex' | 'limit'> = {
const query: Omit<GenreListQuery, 'limit' | 'startIndex'> = {
...filter,
};
@ -122,8 +123,6 @@ export const GenreListGridView = ({ gridRef, itemCount }: any) => {
<AutoSizer>
{({ height, width }: Size) => (
<VirtualInfiniteGrid
key={`album-list-${server?.id}-${display}`}
ref={gridRef}
cardRows={cardRows}
display={display || ListDisplayType.CARD}
fetchFn={fetch}
@ -135,14 +134,16 @@ export const GenreListGridView = ({ gridRef, itemCount }: any) => {
itemGap={grid?.itemGap ?? 10}
itemSize={grid?.itemSize || 200}
itemType={LibraryItem.GENRE}
key={`album-list-${server?.id}-${display}`}
loading={itemCount === undefined || itemCount === null}
minimumBatchSize={40}
onScroll={handleGridScroll}
ref={gridRef}
route={{
route: genrePath,
slugs: [{ idProperty: 'id', slugProperty: 'genreId' }],
}}
width={width}
onScroll={handleGridScroll}
/>
)}
</AutoSizer>

View file

@ -1,7 +1,8 @@
import { ChangeEvent, MouseEvent, MutableRefObject, useCallback, useMemo } from 'react';
import type { AgGridReact as AgGridReactType } from '@ag-grid-community/react/lib/agGridReact';
import { Divider, Flex, Group, Stack } from '@mantine/core';
import { useQueryClient } from '@tanstack/react-query';
import { ChangeEvent, MouseEvent, MutableRefObject, useCallback, useMemo } from 'react';
import { useTranslation } from 'react-i18next';
import {
RiAlbumLine,
@ -11,6 +12,8 @@ import {
RiRefreshLine,
RiSettings3Fill,
} from 'react-icons/ri';
import i18n from '/@/i18n/i18n';
import { queryKeys } from '/@/renderer/api/query-keys';
import {
GenreListQuery,
@ -36,7 +39,6 @@ import {
useSettingsStoreActions,
} from '/@/renderer/store';
import { ListDisplayType, TableColumn } from '/@/renderer/types';
import i18n from '/@/i18n/i18n';
const FILTERS = {
jellyfin: [
@ -63,7 +65,7 @@ const FILTERS = {
};
interface GenreListHeaderFiltersProps {
gridRef: MutableRefObject<VirtualInfiniteGridRef | null>;
gridRef: MutableRefObject<null | VirtualInfiniteGridRef>;
itemCount: number | undefined;
tableRef: MutableRefObject<AgGridReactType | null>;
}
@ -75,15 +77,15 @@ export const GenreListHeaderFilters = ({
}: GenreListHeaderFiltersProps) => {
const { t } = useTranslation();
const queryClient = useQueryClient();
const { pageKey, customFilters } = useListContext();
const { customFilters, pageKey } = useListContext();
const server = useCurrentServer();
const { setFilter, setTable, setGrid, setDisplayType } = useListStoreActions();
const { display, filter, table, grid } = useListStoreByKey<GenreListQuery>({ key: pageKey });
const { setDisplayType, setFilter, setGrid, setTable } = useListStoreActions();
const { display, filter, grid, table } = useListStoreByKey<GenreListQuery>({ key: pageKey });
const cq = useContainerQuery();
const { genreTarget } = useGeneralSettings();
const { setGenreBehavior } = useSettingsStoreActions();
const { handleRefreshTable, handleRefreshGrid } = useListFilterRefresh({
const { handleRefreshGrid, handleRefreshTable } = useListFilterRefresh({
itemCount,
itemType: LibraryItem.GENRE,
server,
@ -265,10 +267,10 @@ export const GenreListHeaderFilters = ({
<DropdownMenu.Dropdown>
{FILTERS[server?.type as keyof typeof FILTERS].map((f) => (
<DropdownMenu.Item
key={`filter-${f.name}`}
$isActive={f.value === filter.sortBy}
value={f.value}
key={`filter-${f.name}`}
onClick={handleSetSortBy}
value={f.value}
>
{f.name}
</DropdownMenu.Item>
@ -277,8 +279,8 @@ export const GenreListHeaderFilters = ({
</DropdownMenu>
<Divider orientation="vertical" />
<OrderToggleButton
sortOrder={filter.sortOrder}
onToggle={handleToggleSortOrder}
sortOrder={filter.sortOrder}
/>
{server?.type === ServerType.JELLYFIN && (
<>
@ -304,10 +306,10 @@ export const GenreListHeaderFilters = ({
<DropdownMenu.Dropdown>
{musicFoldersQuery.data?.items.map((folder) => (
<DropdownMenu.Item
key={`musicFolder-${folder.id}`}
$isActive={filter.musicFolderId === folder.id}
value={folder.id}
key={`musicFolder-${folder.id}`}
onClick={handleSetMusicFolder}
value={folder.id}
>
{folder.name}
</DropdownMenu.Item>
@ -319,10 +321,10 @@ export const GenreListHeaderFilters = ({
<Divider orientation="vertical" />
<Button
compact
onClick={handleRefresh}
size="md"
tooltip={{ label: t('common.refresh', { postProcess: 'titleCase' }) }}
variant="subtle"
onClick={handleRefresh}
>
<RiRefreshLine size="1.3rem" />
</Button>
@ -348,6 +350,7 @@ export const GenreListHeaderFilters = ({
<Divider orientation="vertical" />
<Button
compact
onClick={handleGenreToggle}
size="md"
tooltip={{
label: t(
@ -358,7 +361,6 @@ export const GenreListHeaderFilters = ({
),
}}
variant="subtle"
onClick={handleGenreToggle}
>
{genreTarget === GenreTarget.ALBUM ? <RiAlbumLine /> : <RiMusic2Line />}
</Button>
@ -390,22 +392,22 @@ export const GenreListHeaderFilters = ({
</DropdownMenu.Label>
<DropdownMenu.Item
$isActive={display === ListDisplayType.CARD}
value={ListDisplayType.CARD}
onClick={handleSetViewType}
value={ListDisplayType.CARD}
>
{t('table.config.view.card', { postProcess: 'titleCase' })}
</DropdownMenu.Item>
<DropdownMenu.Item
$isActive={display === ListDisplayType.POSTER}
value={ListDisplayType.POSTER}
onClick={handleSetViewType}
value={ListDisplayType.POSTER}
>
{t('table.config.view.poster', { postProcess: 'titleCase' })}
</DropdownMenu.Item>
<DropdownMenu.Item
$isActive={display === ListDisplayType.TABLE}
value={ListDisplayType.TABLE}
onClick={handleSetViewType}
value={ListDisplayType.TABLE}
>
{t('table.config.view.table', { postProcess: 'titleCase' })}
</DropdownMenu.Item>
@ -458,8 +460,8 @@ export const GenreListHeaderFilters = ({
defaultValue={table?.columns.map(
(column) => column.column,
)}
width={300}
onChange={handleTableColumns}
width={300}
/>
<Group position="apart">
<Text>

View file

@ -1,24 +1,26 @@
import { ChangeEvent, MutableRefObject } from 'react';
import type { AgGridReact as AgGridReactType } from '@ag-grid-community/react/lib/agGridReact';
import { Flex, Group, Stack } from '@mantine/core';
import debounce from 'lodash/debounce';
import { ChangeEvent, MutableRefObject } from 'react';
import { useTranslation } from 'react-i18next';
import { GenreListQuery, LibraryItem } from '/@/renderer/api/types';
import { PageHeader, SearchInput } from '/@/renderer/components';
import { VirtualInfiniteGridRef } from '/@/renderer/components/virtual-grid';
import { GenreListHeaderFilters } from '/@/renderer/features/genres/components/genre-list-header-filters';
import { FilterBar, LibraryHeaderBar } from '/@/renderer/features/shared';
import { useContainerQuery } from '/@/renderer/hooks';
import { GenreListFilter, useCurrentServer } from '/@/renderer/store';
import { useTranslation } from 'react-i18next';
import { useDisplayRefresh } from '/@/renderer/hooks/use-display-refresh';
import { GenreListFilter, useCurrentServer } from '/@/renderer/store';
interface GenreListHeaderProps {
gridRef: MutableRefObject<VirtualInfiniteGridRef | null>;
gridRef: MutableRefObject<null | VirtualInfiniteGridRef>;
itemCount?: number;
tableRef: MutableRefObject<AgGridReactType | null>;
}
export const GenreListHeader = ({ itemCount, gridRef, tableRef }: GenreListHeaderProps) => {
export const GenreListHeader = ({ gridRef, itemCount, tableRef }: GenreListHeaderProps) => {
const { t } = useTranslation();
const cq = useContainerQuery();
const server = useCurrentServer();
@ -57,8 +59,8 @@ export const GenreListHeader = ({ itemCount, gridRef, tableRef }: GenreListHeade
<Group>
<SearchInput
defaultValue={filter.searchTerm}
openedWidth={cq.isMd ? 250 : cq.isSm ? 200 : 150}
onChange={handleSearch}
openedWidth={cq.isMd ? 250 : cq.isSm ? 200 : 150}
/>
</Group>
</Flex>

View file

@ -1,24 +1,26 @@
import { LibraryItem } from '/@/renderer/api/types';
import type { AgGridReact as AgGridReactType } from '@ag-grid-community/react/lib/agGridReact';
import { RowDoubleClickedEvent } from '@ag-grid-community/core';
import { MutableRefObject, useCallback } from 'react';
import { generatePath, useNavigate } from 'react-router';
import { LibraryItem } from '/@/renderer/api/types';
import { VirtualGridAutoSizerContainer } from '/@/renderer/components/virtual-grid';
import { VirtualTable } from '/@/renderer/components/virtual-table';
import { useVirtualTable } from '/@/renderer/components/virtual-table/hooks/use-virtual-table';
import { useListContext } from '/@/renderer/context/list-context';
import { GENRE_CONTEXT_MENU_ITEMS } from '/@/renderer/features/context-menu/context-menu-items';
import { useCurrentServer } from '/@/renderer/store';
import { MutableRefObject, useCallback } from 'react';
import { RowDoubleClickedEvent } from '@ag-grid-community/core';
import { generatePath, useNavigate } from 'react-router';
import { useGenreRoute } from '/@/renderer/hooks/use-genre-route';
import { useCurrentServer } from '/@/renderer/store';
interface GenreListTableViewProps {
itemCount?: number;
tableRef: MutableRefObject<AgGridReactType | null>;
}
export const GenreListTableView = ({ tableRef, itemCount }: GenreListTableViewProps) => {
export const GenreListTableView = ({ itemCount, tableRef }: GenreListTableViewProps) => {
const server = useCurrentServer();
const { pageKey, customFilters } = useListContext();
const { customFilters, pageKey } = useListContext();
const navigate = useNavigate();
const genrePath = useGenreRoute();

View file

@ -1,8 +1,10 @@
import { useQuery } from '@tanstack/react-query';
import { api } from '/@/renderer/api';
import { queryKeys } from '/@/renderer/api/query-keys';
import type { GenreListQuery } from '/@/renderer/api/types';
import type { QueryHookArgs } from '/@/renderer/lib/react-query';
import { useQuery } from '@tanstack/react-query';
import { api } from '/@/renderer/api';
import { queryKeys } from '/@/renderer/api/query-keys';
import { getServerById } from '/@/renderer/store';
export const useGenreList = (args: QueryHookArgs<GenreListQuery>) => {

View file

@ -1,5 +1,10 @@
import { useMemo, useRef } from 'react';
import type { AgGridReact as AgGridReactType } from '@ag-grid-community/react/lib/agGridReact';
import { useMemo, useRef } from 'react';
import { useListStoreByKey } from '../../../store/list.store';
import { GenreListQuery } from '/@/renderer/api/types';
import { VirtualInfiniteGridRef } from '/@/renderer/components/virtual-grid';
import { ListContext } from '/@/renderer/context/list-context';
import { GenreListContent } from '/@/renderer/features/genres/components/genre-list-content';
@ -7,11 +12,9 @@ import { GenreListHeader } from '/@/renderer/features/genres/components/genre-li
import { useGenreList } from '/@/renderer/features/genres/queries/genre-list-query';
import { AnimatedPage } from '/@/renderer/features/shared';
import { useCurrentServer } from '/@/renderer/store';
import { useListStoreByKey } from '../../../store/list.store';
import { GenreListQuery } from '/@/renderer/api/types';
const GenreListRoute = () => {
const gridRef = useRef<VirtualInfiniteGridRef | null>(null);
const gridRef = useRef<null | VirtualInfiniteGridRef>(null);
const tableRef = useRef<AgGridReactType | null>(null);
const server = useCurrentServer();
const pageKey = 'genre';