Redesign sidebar / header and other misc. improvements (#24)

* Remove 1920px max width

* Fix position of list controls menu

* Match size and color of search input

* Adjust library header sizing

* Move app menu to sidebar

* Increase row buffer on play queue list

* Fix query builder styles

* Fix playerbar slider track bg

* Adjust titlebar styles

* Fix invalid modal prop

* Various adjustments to detail pages

* Fix sidebar height calculation

* Fix list null indicators, add filter indicator

* Adjust playqueue styles

* Fix jellyfin releaseYear normalization

* Suppress browser context menu on ag-grid

* Add radius to drawer queue -- normalize layout

* Add modal styles to provider theme

* Fix playlist song list pagination

* Add disc number to albums with more than one disc

* Fix query builder boolean values

* Adjust input placeholder color

* Properly handle rating/favorite from context menu on table

* Conform dropdown menu styles to context menu

* Increase sort type select width

* Fix drawer queue radius

* Change primary color

* Prevent volume wheel from invalid values

* Add icons to query builder dropdowns

* Update notification styles

* Update scrollbar thumb styles

* Remove "add to playlist" on smart playlists

* Fix "add to playlist" from context menu
This commit is contained in:
Jeff 2023-02-07 22:47:23 -08:00 committed by GitHub
parent d2c0d4c11f
commit 9f2e873366
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
80 changed files with 1427 additions and 1101 deletions

View file

@ -26,7 +26,10 @@ import { useQueryClient } from '@tanstack/react-query';
import { AnimatePresence } from 'framer-motion';
import debounce from 'lodash/debounce';
import { useHandleTableContextMenu } from '/@/renderer/features/context-menu';
import { PLAYLIST_SONG_CONTEXT_MENU_ITEMS } from '/@/renderer/features/context-menu/context-menu-items';
import {
PLAYLIST_SONG_CONTEXT_MENU_ITEMS,
SMART_PLAYLIST_SONG_CONTEXT_MENU_ITEMS,
} from '/@/renderer/features/context-menu/context-menu-items';
import { usePlayButtonBehavior } from '/@/renderer/store/settings.store';
import {
LibraryItem,
@ -40,6 +43,7 @@ import { useParams } from 'react-router';
import { usePlayQueueAdd } from '/@/renderer/features/player';
import { api } from '/@/renderer/api';
import { queryKeys } from '/@/renderer/api/query-keys';
import { usePlaylistDetail } from '/@/renderer/features/playlists/queries/playlist-detail-query';
interface PlaylistDetailContentProps {
tableRef: MutableRefObject<AgGridReactType | null>;
@ -57,6 +61,8 @@ export const PlaylistDetailSongListContent = ({ tableRef }: PlaylistDetailConten
};
}, [page?.table.id, playlistId]);
const detailQuery = usePlaylistDetail({ id: playlistId });
const p = usePlaylistDetailTablePagination(playlistId);
const pagination = {
currentPage: p?.currentPage || 0,
@ -115,12 +121,12 @@ export const PlaylistDetailSongListContent = ({ tableRef }: PlaylistDetailConten
);
const songs = api.normalize.songList(songsRes, server);
params.successCallback(songs?.items || [], songsRes?.totalRecordCount);
params.successCallback(songs?.items || [], songsRes?.totalRecordCount || 0);
},
rowCount: undefined,
};
params.api.setDatasource(dataSource);
params.api.ensureIndexVisible(pagination.scrollOffset, 'top');
params.api?.ensureIndexVisible(pagination.scrollOffset, 'top');
},
[filters, pagination.scrollOffset, playlistId, queryClient, server],
);
@ -135,9 +141,13 @@ export const PlaylistDetailSongListContent = ({ tableRef }: PlaylistDetailConten
(event: PaginationChangedEvent) => {
if (!isPaginationEnabled || !event.api) return;
// Scroll to top of page on pagination change
const currentPageStartIndex = pagination.currentPage * pagination.itemsPerPage;
event.api?.ensureIndexVisible(currentPageStartIndex, 'top');
try {
// Scroll to top of page on pagination change
const currentPageStartIndex = pagination.currentPage * pagination.itemsPerPage;
event.api?.ensureIndexVisible(currentPageStartIndex, 'top');
} catch (err) {
console.log(err);
}
setPagination(playlistId, {
itemsPerPage: event.api.paginationGetPageSize(),
@ -185,11 +195,18 @@ export const PlaylistDetailSongListContent = ({ tableRef }: PlaylistDetailConten
setPagination(playlistId, { scrollOffset });
};
const handleContextMenu = useHandleTableContextMenu(
LibraryItem.SONG,
PLAYLIST_SONG_CONTEXT_MENU_ITEMS,
{ playlistId, tableRef },
);
const contextMenuItems = useMemo(() => {
if (detailQuery?.data?.rules) {
return SMART_PLAYLIST_SONG_CONTEXT_MENU_ITEMS;
}
return PLAYLIST_SONG_CONTEXT_MENU_ITEMS;
}, [detailQuery?.data?.rules]);
const handleContextMenu = useHandleTableContextMenu(LibraryItem.SONG, contextMenuItems, {
playlistId,
tableRef,
});
const handleRowDoubleClick = (e: RowDoubleClickedEvent<QueueSong>) => {
if (!e.data) return;
@ -200,45 +217,49 @@ export const PlaylistDetailSongListContent = ({ tableRef }: PlaylistDetailConten
};
return (
<VirtualGridAutoSizerContainer>
<VirtualTable
// https://github.com/ag-grid/ag-grid/issues/5284
// Key is used to force remount of table when display, rowHeight, or server changes
key={`table-${page.display}-${page.table.rowHeight}-${server?.id}`}
ref={tableRef}
alwaysShowHorizontalScroll
autoFitColumns={page.table.autoFit}
columnDefs={columnDefs}
getRowId={(data) => data.data.uniqueId}
infiniteInitialRowCount={checkPlaylistList.data?.totalRecordCount || 1}
pagination={isPaginationEnabled}
paginationAutoPageSize={isPaginationEnabled}
paginationPageSize={pagination.itemsPerPage || 100}
rowHeight={page.table.rowHeight || 40}
rowModelType="infinite"
onBodyScrollEnd={handleScroll}
onCellContextMenu={handleContextMenu}
onColumnMoved={handleColumnChange}
onColumnResized={debouncedColumnChange}
onGridReady={onGridReady}
onGridSizeChanged={handleGridSizeChange}
onPaginationChanged={onPaginationChanged}
onRowDoubleClicked={handleRowDoubleClick}
/>
<AnimatePresence
presenceAffectsLayout
initial={false}
mode="wait"
>
{page.display === ListDisplayType.TABLE_PAGINATED && (
<TablePagination
id={playlistId}
pagination={pagination}
setIdPagination={setPagination}
tableRef={tableRef}
/>
)}
</AnimatePresence>
</VirtualGridAutoSizerContainer>
<>
<VirtualGridAutoSizerContainer>
<VirtualTable
// https://github.com/ag-grid/ag-grid/issues/5284
// Key is used to force remount of table when display, rowHeight, or server changes
key={`table-${page.display}-${page.table.rowHeight}-${server?.id}`}
ref={tableRef}
alwaysShowHorizontalScroll
autoFitColumns={page.table.autoFit}
columnDefs={columnDefs}
getRowId={(data) => data.data.uniqueId}
infiniteInitialRowCount={checkPlaylistList.data?.totalRecordCount || 100}
pagination={isPaginationEnabled}
paginationAutoPageSize={isPaginationEnabled}
paginationPageSize={pagination.itemsPerPage || 100}
rowHeight={page.table.rowHeight || 40}
rowModelType="infinite"
onBodyScrollEnd={handleScroll}
onCellContextMenu={handleContextMenu}
onColumnMoved={handleColumnChange}
onColumnResized={debouncedColumnChange}
onGridReady={onGridReady}
onGridSizeChanged={handleGridSizeChange}
onPaginationChanged={onPaginationChanged}
onRowDoubleClicked={handleRowDoubleClick}
/>
</VirtualGridAutoSizerContainer>
{isPaginationEnabled && (
<AnimatePresence
presenceAffectsLayout
initial={false}
mode="wait"
>
{page.display === ListDisplayType.TABLE_PAGINATED && (
<TablePagination
id={playlistId}
pagination={pagination}
setIdPagination={setPagination}
tableRef={tableRef}
/>
)}
</AnimatePresence>
)}
</>
);
};