You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
221 lines
7.9 KiB
221 lines
7.9 KiB
import React, { useEffect, useRef, useState } from 'react';
|
|
import settings from 'electron-settings';
|
|
import _ from 'lodash';
|
|
import { useQuery, useQueryClient } from 'react-query';
|
|
import { useHistory } from 'react-router-dom';
|
|
import { ButtonToolbar, Icon } from 'rsuite';
|
|
import { useTranslation } from 'react-i18next';
|
|
import ListViewType from '../viewtypes/ListViewType';
|
|
import { useAppDispatch, useAppSelector } from '../../redux/hooks';
|
|
import GenericPage from '../layout/GenericPage';
|
|
import GenericPageHeader from '../layout/GenericPageHeader';
|
|
import { StyledButton, StyledInputPicker, StyledInputPickerContainer } from '../shared/styled';
|
|
import { fixPlayer2Index, setPlayQueueByRowClick } from '../../redux/playQueueSlice';
|
|
import { setStatus } from '../../redux/playerSlice';
|
|
import useSearchQuery from '../../hooks/useSearchQuery';
|
|
import { setCurrentViewedFolder } from '../../redux/folderSlice';
|
|
import useRouterQuery from '../../hooks/useRouterQuery';
|
|
import { Server } from '../../types';
|
|
import { apiController } from '../../api/controller';
|
|
import CenterLoader from '../loader/CenterLoader';
|
|
import useListClickHandler from '../../hooks/useListClickHandler';
|
|
import useFavorite from '../../hooks/useFavorite';
|
|
import { useRating } from '../../hooks/useRating';
|
|
|
|
const FolderList = () => {
|
|
const { t } = useTranslation();
|
|
const dispatch = useAppDispatch();
|
|
const history = useHistory();
|
|
const query = useRouterQuery();
|
|
const queryClient = useQueryClient();
|
|
const folder = useAppSelector((state) => state.folder);
|
|
const config = useAppSelector((state) => state.config);
|
|
const misc = useAppSelector((state) => state.misc);
|
|
const [musicFolder, setMusicFolder] = useState(folder.musicFolder);
|
|
const folderPickerContainerRef = useRef(null);
|
|
|
|
const {
|
|
isLoading,
|
|
isError,
|
|
data: indexData,
|
|
error,
|
|
}: any = useQuery(['indexes', musicFolder], () =>
|
|
apiController({
|
|
serverType: config.serverType,
|
|
endpoint: 'getIndexes',
|
|
args: config.serverType === Server.Subsonic ? { musicFolderId: musicFolder } : null,
|
|
})
|
|
);
|
|
|
|
const { isLoading: isLoadingFolderData, data: folderData }: any = useQuery(
|
|
['folder', folder.currentViewedFolder],
|
|
() =>
|
|
apiController({
|
|
serverType: config.serverType,
|
|
endpoint: 'getMusicDirectory',
|
|
args: { id: folder.currentViewedFolder },
|
|
}),
|
|
{
|
|
enabled: folder.currentViewedFolder !== '',
|
|
}
|
|
);
|
|
|
|
const { isLoading: isLoadingMusicFolders, data: musicFolders } = useQuery(['musicFolders'], () =>
|
|
apiController({ serverType: config.serverType, endpoint: 'getMusicFolders' })
|
|
);
|
|
|
|
const filteredData = useSearchQuery(
|
|
misc.searchQuery,
|
|
folderData?.id ? folderData?.child : indexData,
|
|
['title', 'artist', 'album', 'year', 'genre', 'path']
|
|
);
|
|
|
|
useEffect(() => {
|
|
if (query.get('folderId') !== 'null') {
|
|
dispatch(setCurrentViewedFolder(query.get('folderId') || ''));
|
|
}
|
|
}, [dispatch, query]);
|
|
|
|
const { handleRowClick, handleRowDoubleClick } = useListClickHandler({
|
|
doubleClick: (rowData: any) => {
|
|
if (rowData.isDir) {
|
|
history.push(`/library/folder?folderId=${rowData.id}`);
|
|
dispatch(setCurrentViewedFolder(rowData.id));
|
|
} else {
|
|
const selected = folderData?.id ? folderData?.child : indexData?.child;
|
|
dispatch(
|
|
setPlayQueueByRowClick({
|
|
entries: selected.filter((entry: any) => entry?.isDir === false),
|
|
currentIndex: rowData.rowIndex,
|
|
currentSongId: rowData.id,
|
|
uniqueSongId: rowData.uniqueId,
|
|
filters: config.playback.filters,
|
|
})
|
|
);
|
|
dispatch(setStatus('PLAYING'));
|
|
dispatch(fixPlayer2Index());
|
|
}
|
|
},
|
|
});
|
|
|
|
const { handleFavorite } = useFavorite();
|
|
const { handleRating } = useRating();
|
|
|
|
return (
|
|
<>
|
|
{(isLoading || isLoadingMusicFolders) && <CenterLoader />}
|
|
{isError && <div>Error: {error}</div>}
|
|
{!isLoading && indexData && (
|
|
<GenericPage
|
|
hideDivider
|
|
header={
|
|
<GenericPageHeader
|
|
title={`${
|
|
folderData?.title
|
|
? folderData.title
|
|
: isLoadingFolderData
|
|
? t('Loading...')
|
|
: t('Select a folder')
|
|
}`}
|
|
showTitleTooltip
|
|
subtitle={
|
|
<>
|
|
<StyledInputPickerContainer ref={folderPickerContainerRef}>
|
|
<ButtonToolbar>
|
|
<StyledInputPicker
|
|
container={() => folderPickerContainerRef.current}
|
|
size="sm"
|
|
width={180}
|
|
data={musicFolders}
|
|
defaultValue={musicFolder}
|
|
valueKey="id"
|
|
labelKey="title"
|
|
placeholder={t('Select')}
|
|
onChange={(e: any) => {
|
|
setMusicFolder(e);
|
|
}}
|
|
disabled={config.serverType === Server.Jellyfin}
|
|
/>
|
|
|
|
<StyledButton
|
|
size="sm"
|
|
onClick={() => {
|
|
history.push(
|
|
`/library/folder?folderId=${
|
|
folderData?.parent ? folderData.parent : ''
|
|
}`
|
|
);
|
|
dispatch(
|
|
setCurrentViewedFolder(folderData?.parent ? folderData.parent : '')
|
|
);
|
|
}}
|
|
>
|
|
<Icon icon="level-up" style={{ marginRight: '10px' }} />
|
|
{t('Go up')}
|
|
</StyledButton>
|
|
</ButtonToolbar>
|
|
</StyledInputPickerContainer>
|
|
</>
|
|
}
|
|
/>
|
|
}
|
|
>
|
|
<ListViewType
|
|
data={
|
|
misc.searchQuery !== ''
|
|
? filteredData
|
|
: folder.currentViewedFolder
|
|
? folderData?.child
|
|
: indexData
|
|
}
|
|
loading={isLoadingFolderData}
|
|
tableColumns={settings.getSync('musicListColumns')}
|
|
rowHeight={Number(settings.getSync('musicListRowHeight'))}
|
|
fontSize={Number(settings.getSync('musicListFontSize'))}
|
|
handleRowClick={handleRowClick}
|
|
handleRowDoubleClick={handleRowDoubleClick}
|
|
handleFavorite={(rowData: any) =>
|
|
handleFavorite(rowData, {
|
|
custom: () => {
|
|
queryClient.setQueryData(
|
|
['folder', folder.currentViewedFolder],
|
|
(oldData: any) => {
|
|
const starredIndices = _.keys(_.pickBy(oldData.child, { id: rowData.id }));
|
|
starredIndices.forEach((index) => {
|
|
oldData.child[index].starred = rowData.starred ? undefined : Date.now();
|
|
});
|
|
|
|
return oldData;
|
|
}
|
|
);
|
|
},
|
|
})
|
|
}
|
|
handleRating={(rowData: any, rating: number) =>
|
|
handleRating(rowData, { queryKey: ['folder', folder.currentViewedFolder], rating })
|
|
}
|
|
cacheImages={{
|
|
enabled: settings.getSync('cacheImages'),
|
|
cacheType: 'folder',
|
|
cacheIdProperty: 'albumId',
|
|
}}
|
|
page="folderListPage"
|
|
listType="folder"
|
|
virtualized
|
|
disabledContextMenuOptions={[
|
|
'addToFavorites',
|
|
'removeFromFavorites',
|
|
'viewInModal',
|
|
'moveSelectedTo',
|
|
'removeSelected',
|
|
'deletePlaylist',
|
|
'viewInFolder',
|
|
]}
|
|
/>
|
|
</GenericPage>
|
|
)}
|
|
</>
|
|
);
|
|
};
|
|
|
|
export default FolderList;
|
|
|