Browse Source
- - Add genre sort to getAllAlbums api - Add genres to sortType picker - Add router query param for sortType on album list - Remove deprecated LibraryView pagemaster
jeffvli
3 years ago
8 changed files with 303 additions and 166 deletions
@ -0,0 +1,93 @@ |
|||
import React, { useState } from 'react'; |
|||
import settings from 'electron-settings'; |
|||
import { useQuery } from 'react-query'; |
|||
import { useHistory } from 'react-router'; |
|||
import useSearchQuery from '../../hooks/useSearchQuery'; |
|||
import GenericPage from '../layout/GenericPage'; |
|||
import GenericPageHeader from '../layout/GenericPageHeader'; |
|||
import ListViewType from '../viewtypes/ListViewType'; |
|||
import PageLoader from '../loader/PageLoader'; |
|||
import { useAppDispatch } from '../../redux/hooks'; |
|||
import { |
|||
clearSelected, |
|||
setRangeSelected, |
|||
toggleRangeSelected, |
|||
toggleSelected, |
|||
} from '../../redux/multiSelectSlice'; |
|||
import { getGenres } from '../../api/api'; |
|||
|
|||
const GenreList = () => { |
|||
const dispatch = useAppDispatch(); |
|||
const history = useHistory(); |
|||
const { isLoading, isError, data: genres, error }: any = useQuery(['genreList'], () => |
|||
getGenres() |
|||
); |
|||
const [searchQuery, setSearchQuery] = useState(''); |
|||
const filteredData = useSearchQuery(searchQuery, genres, ['value']); |
|||
|
|||
let timeout: any = null; |
|||
const handleRowClick = (e: any, rowData: any) => { |
|||
if (timeout === null) { |
|||
timeout = window.setTimeout(() => { |
|||
timeout = null; |
|||
|
|||
if (e.ctrlKey) { |
|||
dispatch(toggleSelected(rowData)); |
|||
} else if (e.shiftKey) { |
|||
dispatch(setRangeSelected(rowData)); |
|||
dispatch(toggleRangeSelected(searchQuery !== '' ? filteredData : genres)); |
|||
} |
|||
}, 100); |
|||
} |
|||
}; |
|||
|
|||
const handleRowDoubleClick = (rowData: any) => { |
|||
window.clearTimeout(timeout); |
|||
timeout = null; |
|||
|
|||
dispatch(clearSelected()); |
|||
history.push(`/library/album?sortType=${rowData.value}`); |
|||
}; |
|||
|
|||
return ( |
|||
<GenericPage |
|||
hideDivider |
|||
header={ |
|||
<GenericPageHeader |
|||
title="Genres" |
|||
searchQuery={searchQuery} |
|||
handleSearch={(e: any) => setSearchQuery(e)} |
|||
clearSearchQuery={() => setSearchQuery('')} |
|||
viewTypeSetting="genre" |
|||
showSearchBar |
|||
/> |
|||
} |
|||
> |
|||
{isLoading && <PageLoader />} |
|||
{isError && <div>Error: {error}</div>} |
|||
{!isLoading && !isError && ( |
|||
<ListViewType |
|||
data={searchQuery !== '' ? filteredData : genres} |
|||
tableColumns={settings.getSync('genreListColumns')} |
|||
rowHeight={Number(settings.getSync('genreListRowHeight'))} |
|||
fontSize={settings.getSync('genreListFontSize')} |
|||
handleRowClick={handleRowClick} |
|||
handleRowDoubleClick={handleRowDoubleClick} |
|||
listType="genre" |
|||
virtualized |
|||
disabledContextMenuOptions={[ |
|||
'addToQueue', |
|||
'moveSelectedTo', |
|||
'removeFromCurrent', |
|||
'addToPlaylist', |
|||
'deletePlaylist', |
|||
'addToFavorites', |
|||
'removeFromFavorites', |
|||
]} |
|||
/> |
|||
)} |
|||
</GenericPage> |
|||
); |
|||
}; |
|||
|
|||
export default GenreList; |
@ -1,133 +0,0 @@ |
|||
import React, { useState } from 'react'; |
|||
import { Nav, SelectPicker } from 'rsuite'; |
|||
import { useQuery } from 'react-query'; |
|||
import VisibilitySensor from 'react-visibility-sensor'; |
|||
import settings from 'electron-settings'; |
|||
import _ from 'lodash'; |
|||
import useSearchQuery from '../../hooks/useSearchQuery'; |
|||
import { getAlbumsDirect, getArtists } from '../../api/api'; |
|||
import GenericPage from '../layout/GenericPage'; |
|||
import GenericPageHeader from '../layout/GenericPageHeader'; |
|||
import ArtistList from './ArtistList'; |
|||
import PageLoader from '../loader/PageLoader'; |
|||
|
|||
const ALBUM_SORT_TYPES = [ |
|||
{ label: 'A-Z (Name)', value: 'alphabeticalByName' }, |
|||
{ |
|||
label: 'A-Z (Artist)', |
|||
value: 'alphabeticalByArtist', |
|||
}, |
|||
{ label: 'Most Played', value: 'frequent' }, |
|||
{ label: 'Newly Added', value: 'newest' }, |
|||
{ label: 'Recently Played', value: 'recent' }, |
|||
]; |
|||
|
|||
const LibraryView = () => { |
|||
const [currentPage, setCurrentPage] = useState('albums'); |
|||
const [sortBy, setSortBy] = useState(null); |
|||
const [data, setData] = useState<any[]>([]); |
|||
const [offset, setOffset] = useState(0); |
|||
const [viewType, setViewType] = useState(settings.getSync('albumViewType')); |
|||
const { isLoading: isLoadingArtists, data: artists }: any = useQuery('artists', getArtists, { |
|||
enabled: currentPage === 'artists', |
|||
}); |
|||
const [searchQuery, setSearchQuery] = useState(''); |
|||
const filteredData = useSearchQuery( |
|||
searchQuery, |
|||
currentPage === 'artists' ? artists : currentPage === 'albums' ? data : data, |
|||
['name', 'artist'] |
|||
); |
|||
|
|||
const onChange = (isVisible: boolean) => { |
|||
if (isVisible) { |
|||
setOffset(offset + 50); |
|||
|
|||
setTimeout(async () => { |
|||
const res = await getAlbumsDirect({ |
|||
type: sortBy || 'random', |
|||
size: 50, |
|||
offset, |
|||
}); |
|||
|
|||
const combinedData = data.concat(res); |
|||
|
|||
// Ensure that no duplicates are added in the case of random fetching
|
|||
const uniqueCombinedData = _.uniqBy(combinedData, (e: any) => e.id); |
|||
|
|||
return setData(uniqueCombinedData); |
|||
}, 0); |
|||
} |
|||
}; |
|||
|
|||
const handleNavClick = (e: React.SetStateAction<string>) => { |
|||
setData([]); |
|||
setOffset(0); |
|||
setCurrentPage(e); |
|||
}; |
|||
|
|||
return ( |
|||
<GenericPage |
|||
header={ |
|||
<GenericPageHeader |
|||
title="Library" |
|||
subtitle={ |
|||
<Nav activeKey={currentPage} onSelect={handleNavClick}> |
|||
<Nav.Item eventKey="albums">Albums</Nav.Item> |
|||
<Nav.Item eventKey="artists">Artists</Nav.Item> |
|||
<Nav.Item eventKey="genres">Genres</Nav.Item> |
|||
</Nav> |
|||
} |
|||
subsidetitle={ |
|||
currentPage === 'albums' ? ( |
|||
<SelectPicker |
|||
data={ALBUM_SORT_TYPES} |
|||
searchable={false} |
|||
placeholder="Sort Type" |
|||
menuAutoWidth |
|||
onChange={(value) => { |
|||
setData([]); |
|||
setOffset(0); |
|||
setSortBy(value); |
|||
}} |
|||
/> |
|||
) : undefined |
|||
} |
|||
searchQuery={searchQuery} |
|||
handleSearch={(e: any) => setSearchQuery(e)} |
|||
clearSearchQuery={() => setSearchQuery('')} |
|||
showViewTypeButtons={currentPage === 'albums'} |
|||
viewTypeSetting="album" |
|||
showSearchBar |
|||
handleListClick={() => setViewType('list')} |
|||
handleGridClick={() => setViewType('grid')} |
|||
/> |
|||
} |
|||
> |
|||
{isLoadingArtists && <PageLoader />} |
|||
|
|||
{artists && ( |
|||
<> |
|||
{currentPage === 'artists' && ( |
|||
<ArtistList viewType={viewType} data={searchQuery === '' ? artists : filteredData} /> |
|||
)} |
|||
</> |
|||
)} |
|||
|
|||
{data.length !== 1 && searchQuery === '' && currentPage === 'albums' && ( |
|||
<VisibilitySensor onChange={onChange}> |
|||
<div |
|||
style={{ |
|||
textAlign: 'center', |
|||
marginTop: '25px', |
|||
marginBottom: '25px', |
|||
}} |
|||
> |
|||
<PageLoader size="md" /> |
|||
</div> |
|||
</VisibilitySensor> |
|||
)} |
|||
</GenericPage> |
|||
); |
|||
}; |
|||
|
|||
export default LibraryView; |
Loading…
Reference in new issue