Browse Source

Add types, normalize API returns

master
jeffvli 3 years ago
committed by Jeff
parent
commit
4af81d4404
  1. 14
      src/__tests__/App.test.tsx
  2. 802
      src/api/api.ts
  3. 108
      src/api/types.ts
  4. 10
      src/components/card/Card.tsx
  5. 56
      src/components/dashboard/Dashboard.tsx
  6. 16
      src/components/library/AlbumList.tsx
  7. 4
      src/components/library/AlbumView.tsx
  8. 4
      src/components/library/ArtistList.tsx
  9. 22
      src/components/library/ArtistView.tsx
  10. 10
      src/components/library/FolderList.tsx
  11. 6
      src/components/library/GenreList.tsx
  12. 29
      src/components/player/NowPlayingMiniView.tsx
  13. 28
      src/components/player/NowPlayingView.tsx
  14. 9
      src/components/playlist/PlaylistList.tsx
  15. 4
      src/components/playlist/PlaylistView.tsx
  16. 4
      src/components/search/SearchView.tsx
  17. 46
      src/components/settings/ListViewColumns.ts
  18. 26
      src/components/shared/ContextMenu.tsx
  19. 10
      src/components/starred/StarredView.tsx

14
src/__tests__/App.test.tsx

@ -220,7 +220,7 @@ const configState: ConfigPage = {
},
{
id: 'Title',
dataKey: 'name',
dataKey: 'title',
alignment: 'left',
flexGrow: 5,
label: 'Title',
@ -276,11 +276,11 @@ const configState: ConfigPage = {
label: 'CoverArt',
},
{
id: 'Name',
dataKey: 'name',
id: 'Title',
dataKey: 'title',
alignment: 'left',
flexGrow: 5,
label: 'Name',
label: 'Title',
},
{
id: 'Albums',
@ -311,11 +311,11 @@ const configState: ConfigPage = {
label: '#',
},
{
id: 'Name',
dataKey: 'name',
id: 'Title',
dataKey: 'title',
alignment: 'left',
flexGrow: 5,
label: 'Name',
label: 'Tame',
},
{
id: 'Albums',

802
src/api/api.ts

File diff suppressed because it is too large

108
src/api/types.ts

@ -3,6 +3,112 @@ export enum Server {
Jellyfin = 'jellyfin',
}
export type ServerType = Server.Subsonic | Server.Jellyfin;
export enum Item {
Album = 'album',
Artist = 'artist',
Folder = 'folder',
Genre = 'genre',
Music = 'music',
Playlist = 'playlist',
}
export type ServerType = Server.Subsonic | Server.Jellyfin;
export type APIEndpoints = 'getPlaylist' | 'getPlaylists';
export interface Album {
id: string;
title: string;
isDir?: boolean;
albumId: string;
artist?: string;
artistId?: string;
songCount: number;
duration: number;
created: string;
year?: number;
genre?: string;
image: string;
starred?: string;
type: Item.Album;
uniqueId: string;
song?: Song[];
}
export interface Artist {
id: string;
title: string;
albumCount: number;
image: string;
starred?: string;
type: Item.Artist;
uniqueId: string;
album: Album[];
}
export interface ArtistInfo {
biography?: string;
lastFmUrl?: string;
imageUrl?: string;
similarArtist?: Artist[];
}
export interface Folder {
id: string;
title: string;
isDir?: boolean;
image: string;
type: Item.Folder;
uniqueId: string;
}
export interface Genre {
id: string;
title: string;
songCount?: number;
albumCount?: number;
type: Item.Genre;
uniqueId: string;
}
export interface Playlist {
id: string;
title: string;
comment?: string;
owner: string;
public?: boolean;
songCount: number;
duration: number;
created: string;
changed: string;
image: string;
type: Item.Playlist;
uniqueId: string;
song?: Song[];
}
export interface Song {
id: string;
parent?: string;
title: string;
isDir?: boolean;
album: string;
albumId?: string;
artist: string;
artistId?: string;
track?: number;
year?: number;
genre?: string;
size: number;
contentType?: string;
suffix?: string;
duration?: number;
bitRate?: number;
path?: string;
playCount?: number;
discNumber?: number;
created: string;
streamUrl: string;
image: string;
starred?: string;
type: Item.Music;
uniqueId: string;
}

10
src/components/card/Card.tsx

@ -2,7 +2,7 @@ import React from 'react';
import { Icon } from 'rsuite';
import { useHistory } from 'react-router-dom';
import cacheImage from '../shared/cacheImage';
import { getAlbum, getPlaylist, getAllArtistSongs } from '../../api/api';
import { getAlbum, getPlaylist, getArtistSongs } from '../../api/api';
import { useAppDispatch, useAppSelector } from '../../redux/hooks';
import {
appendPlayQueue,
@ -76,7 +76,7 @@ const Card = ({
}
if (playClick.type === 'album') {
const res = await getAlbum(playClick.id);
const res = await getAlbum({ id: playClick.id });
const songs = filterPlayQueue(config.playback.filters, res.song);
if (songs.entries.length > 0) {
@ -92,7 +92,7 @@ const Card = ({
}
if (playClick.type === 'artist') {
const res = await getAllArtistSongs(playClick.id);
const res = await getArtistSongs({ id: playClick.id });
const songs = filterPlayQueue(config.playback.filters, res);
if (songs.entries.length > 0) {
@ -122,7 +122,7 @@ const Card = ({
}
if (playClick.type === 'album') {
const res = await getAlbum(playClick.id);
const res = await getAlbum({ id: playClick.id });
const songs = filterPlayQueue(config.playback.filters, res.song);
if (songs.entries.length > 0) {
@ -134,7 +134,7 @@ const Card = ({
}
if (playClick.type === 'artist') {
const res = await getAllArtistSongs(playClick.id);
const res = await getArtistSongs({ id: playClick.id });
const songs = filterPlayQueue(config.playback.filters, res);
if (songs.entries.length > 0) {

56
src/components/dashboard/Dashboard.tsx

@ -28,22 +28,22 @@ const Dashboard = () => {
const { isLoading: isLoadingRecent, data: recentAlbums }: any = useQuery(
['recentAlbums', musicFolder],
() => getAlbums({ type: 'recent', size: 20, musicFolderId: musicFolder })
() => getAlbums({ type: 'recent', size: 20, offset: 0, musicFolderId: musicFolder })
);
const { isLoading: isLoadingNewest, data: newestAlbums }: any = useQuery(
['newestAlbums', musicFolder],
() => getAlbums({ type: 'newest', size: 20, musicFolderId: musicFolder })
() => getAlbums({ type: 'newest', size: 20, offset: 0, musicFolderId: musicFolder })
);
const { isLoading: isLoadingRandom, data: randomAlbums }: any = useQuery(
['randomAlbums', musicFolder],
() => getAlbums({ type: 'random', size: 20, musicFolderId: musicFolder })
() => getAlbums({ type: 'random', size: 20, offset: 0, musicFolderId: musicFolder })
);
const { isLoading: isLoadingFrequent, data: frequentAlbums }: any = useQuery(
['frequentAlbums', musicFolder],
() => getAlbums({ type: 'frequent', size: 20, musicFolderId: musicFolder })
() => getAlbums({ type: 'frequent', size: 20, offset: 0, musicFolderId: musicFolder })
);
const handleFavorite = async (rowData: any) => {
@ -51,33 +51,33 @@ const Dashboard = () => {
await star(rowData.id, 'album');
dispatch(setStar({ id: [rowData.id], type: 'star' }));
queryClient.setQueryData(['recentAlbums', musicFolder], (oldData: any) => {
const starredIndices = _.keys(_.pickBy(oldData?.album, { id: rowData.id }));
const starredIndices = _.keys(_.pickBy(oldData, { id: rowData.id }));
starredIndices.forEach((index) => {
oldData.album[index].starred = Date.now();
oldData[index].starred = Date.now();
});
return oldData;
});
queryClient.setQueryData(['newestAlbums', musicFolder], (oldData: any) => {
const starredIndices = _.keys(_.pickBy(oldData?.album, { id: rowData.id }));
const starredIndices = _.keys(_.pickBy(oldData, { id: rowData.id }));
starredIndices.forEach((index) => {
oldData.album[index].starred = Date.now();
oldData[index].starred = Date.now();
});
return oldData;
});
queryClient.setQueryData(['randomAlbums', musicFolder], (oldData: any) => {
const starredIndices = _.keys(_.pickBy(oldData?.album, { id: rowData.id }));
const starredIndices = _.keys(_.pickBy(oldData, { id: rowData.id }));
starredIndices.forEach((index) => {
oldData.album[index].starred = Date.now();
oldData[index].starred = Date.now();
});
return oldData;
});
queryClient.setQueryData(['frequentAlbums', musicFolder], (oldData: any) => {
const starredIndices = _.keys(_.pickBy(oldData?.album, { id: rowData.id }));
const starredIndices = _.keys(_.pickBy(oldData, { id: rowData.id }));
starredIndices.forEach((index) => {
oldData.album[index].starred = Date.now();
oldData[index].starred = Date.now();
});
return oldData;
@ -86,33 +86,33 @@ const Dashboard = () => {
await unstar(rowData.id, 'album');
dispatch(setStar({ id: [rowData.id], type: 'unstar' }));
queryClient.setQueryData(['recentAlbums', musicFolder], (oldData: any) => {
const starredIndices = _.keys(_.pickBy(oldData?.album, { id: rowData.id }));
const starredIndices = _.keys(_.pickBy(oldData, { id: rowData.id }));
starredIndices.forEach((index) => {
oldData.album[index].starred = undefined;
oldData[index].starred = undefined;
});
return oldData;
});
queryClient.setQueryData(['newestAlbums', musicFolder], (oldData: any) => {
const starredIndices = _.keys(_.pickBy(oldData?.album, { id: rowData.id }));
const starredIndices = _.keys(_.pickBy(oldData, { id: rowData.id }));
starredIndices.forEach((index) => {
oldData.album[index].starred = undefined;
oldData[index].starred = undefined;
});
return oldData;
});
queryClient.setQueryData(['randomAlbums', musicFolder], (oldData: any) => {
const starredIndices = _.keys(_.pickBy(oldData?.album, { id: rowData.id }));
const starredIndices = _.keys(_.pickBy(oldData, { id: rowData.id }));
starredIndices.forEach((index) => {
oldData.album[index].starred = undefined;
oldData[index].starred = undefined;
});
return oldData;
});
queryClient.setQueryData(['frequentAlbums', musicFolder], (oldData: any) => {
const starredIndices = _.keys(_.pickBy(oldData?.album, { id: rowData.id }));
const starredIndices = _.keys(_.pickBy(oldData, { id: rowData.id }));
starredIndices.forEach((index) => {
oldData.album[index].starred = undefined;
oldData[index].starred = undefined;
});
return oldData;
@ -134,10 +134,10 @@ const Dashboard = () => {
<>
<ScrollingMenu
title="Recently Played"
data={recentAlbums.album}
data={recentAlbums}
cardTitle={{
prefix: '/library/album',
property: 'name',
property: 'title',
urlProperty: 'albumId',
}}
cardSubtitle={{
@ -158,10 +158,10 @@ const Dashboard = () => {
<ScrollingMenu
title="Recently Added"
data={newestAlbums.album}
data={newestAlbums}
cardTitle={{
prefix: '/library/album',
property: 'name',
property: 'title',
urlProperty: 'albumId',
}}
cardSubtitle={{
@ -182,10 +182,10 @@ const Dashboard = () => {
<ScrollingMenu
title="Random"
data={randomAlbums.album}
data={randomAlbums}
cardTitle={{
prefix: '/library/album',
property: 'name',
property: 'title',
urlProperty: 'albumId',
}}
cardSubtitle={{
@ -206,10 +206,10 @@ const Dashboard = () => {
<ScrollingMenu
title="Most Played"
data={frequentAlbums.album}
data={frequentAlbums}
cardTitle={{
prefix: '/library/album',
property: 'name',
property: 'title',
urlProperty: 'albumId',
}}
cardSubtitle={{

16
src/components/library/AlbumList.tsx

@ -9,7 +9,7 @@ import ListViewType from '../viewtypes/ListViewType';
import useSearchQuery from '../../hooks/useSearchQuery';
import GenericPageHeader from '../layout/GenericPageHeader';
import GenericPage from '../layout/GenericPage';
import { getAlbumsDirect, getAllAlbums, getGenres, star, unstar } from '../../api/api';
import { getAlbums, getGenres, star, unstar } from '../../api/api';
import PageLoader from '../loader/PageLoader';
import { useAppDispatch, useAppSelector } from '../../redux/hooks';
import {
@ -56,16 +56,18 @@ const AlbumList = () => {
['albumList', album.active.filter, musicFolder],
() =>
album.active.filter === 'random'
? getAlbumsDirect({
? getAlbums({
type: 'random',
size: config.lookAndFeel.gridView.cardSize,
offset: 0,
musicFolderId: musicFolder,
})
: getAllAlbums({
: getAlbums({
type: album.active.filter,
size: 500,
offset: 0,
musicFolderId: musicFolder,
recursive: true,
}),
{
cacheTime: 3600000, // Stay in cache for 1 hour
@ -77,8 +79,8 @@ const AlbumList = () => {
return res.map((genre: any) => {
if (genre.albumCount !== 0) {
return {
label: `${genre.value} (${genre.albumCount})`,
value: genre.value,
label: `${genre.title} (${genre.albumCount})`,
value: genre.title,
role: 'Genre',
};
}
@ -86,7 +88,7 @@ const AlbumList = () => {
});
});
const filteredData = useSearchQuery(misc.searchQuery, albums, [
'name',
'title',
'artist',
'genre',
'year',
@ -228,7 +230,7 @@ const AlbumList = () => {
data={misc.searchQuery !== '' ? filteredData : albums}
cardTitle={{
prefix: '/library/album',
property: 'name',
property: 'title',
urlProperty: 'albumId',
}}
cardSubtitle={{

4
src/components/library/AlbumView.tsx

@ -68,7 +68,7 @@ const AlbumView = ({ ...rest }: any) => {
const albumId = rest.id ? rest.id : id;
const { isLoading, isError, data, error }: any = useQuery(['album', albumId], () =>
getAlbum(albumId)
getAlbum({ id: albumId })
);
const filteredData = useSearchQuery(misc.searchQuery, data?.song, [
'title',
@ -240,7 +240,7 @@ const AlbumView = ({ ...rest }: any) => {
id: data.albumId,
}}
imageHeight={200}
title={data.name}
title={data.title}
showTitleTooltip
subtitle={
<div>

4
src/components/library/ArtistList.tsx

@ -45,7 +45,7 @@ const ArtistList = () => {
staleTime: Infinity, // Only allow manual refresh
}
);
const filteredData = useSearchQuery(misc.searchQuery, artists, ['name']);
const filteredData = useSearchQuery(misc.searchQuery, artists, ['title']);
let timeout: any = null;
const handleRowClick = (e: any, rowData: any, tableData: any) => {
@ -151,7 +151,7 @@ const ArtistList = () => {
data={misc.searchQuery !== '' ? filteredData : artists}
cardTitle={{
prefix: '/library/artist',
property: 'name',
property: 'title',
urlProperty: 'id',
}}
cardSubtitle={{

22
src/components/library/ArtistView.tsx

@ -16,7 +16,7 @@ import {
} from '../shared/ToolbarButtons';
import {
getAlbum,
getAllArtistSongs,
getArtistSongs,
getArtist,
getArtistInfo,
getDownloadUrl,
@ -75,17 +75,17 @@ const ArtistView = ({ ...rest }: any) => {
const { id } = useParams<ArtistParams>();
const artistId = rest.id ? rest.id : id;
const { isLoading, isError, data, error }: any = useQuery(['artist', artistId], () =>
getArtist(artistId)
getArtist({ id: artistId })
);
const {
isLoading: isLoadingAI,
isError: isErrorAI,
data: artistInfo,
error: errorAI,
}: any = useQuery(['artistInfo', artistId], () => getArtistInfo(artistId, 8));
}: any = useQuery(['artistInfo', artistId], () => getArtistInfo({ id: artistId, count: 8 }));
const filteredData = useSearchQuery(misc.searchQuery, data?.album, [
'name',
'title',
'artist',
'genre',
'year',
@ -125,7 +125,7 @@ const ArtistView = ({ ...rest }: any) => {
};
const handlePlay = async () => {
const res = await getAllArtistSongs(data.id);
const res = await getArtistSongs({ id: data.id });
const songs = filterPlayQueue(config.playback.filters, res);
if (songs.entries.length > 0) {
@ -141,7 +141,7 @@ const ArtistView = ({ ...rest }: any) => {
};
const handlePlayAppend = async (type: 'next' | 'later') => {
const res = await getAllArtistSongs(data.id);
const res = await getArtistSongs({ id: data.id });
const songs = filterPlayQueue(config.playback.filters, res);
if (songs.entries.length > 0) {
@ -189,11 +189,11 @@ const ArtistView = ({ ...rest }: any) => {
for (let i = 0; i < data.album.length; i += 1) {
// eslint-disable-next-line no-await-in-loop
const albumRes = await getAlbum(data.album[i].id);
const albumRes = await getAlbum({ id: data.album[i].id });
if (albumRes.song[0]?.parent) {
downloadUrls.push(getDownloadUrl(albumRes.song[0].parent));
} else {
notifyToast('warning', `[${albumRes.name}] No parent album found`);
notifyToast('warning', `[${albumRes.title}] No parent album found`);
}
}
@ -295,7 +295,7 @@ const ArtistView = ({ ...rest }: any) => {
id: data.id,
}}
imageHeight={185}
title={data.name}
title={data.title}
showTitleTooltip
subtitle={
<>
@ -393,7 +393,7 @@ const ArtistView = ({ ...rest }: any) => {
}
}}
>
{artist.name}
{artist.title}
</StyledTag>
))}
</TagGroup>
@ -455,7 +455,7 @@ const ArtistView = ({ ...rest }: any) => {
data={misc.searchQuery !== '' ? filteredData : data.album}
cardTitle={{
prefix: '/library/album',
property: 'name',
property: 'title',
urlProperty: 'albumId',
}}
cardSubtitle={{

10
src/components/library/FolderList.tsx

@ -61,7 +61,7 @@ const FolderList = () => {
const filteredData = useSearchQuery(
misc.searchQuery,
folderData?.id ? folderData?.child : indexData,
['name', 'title', 'artist', 'album', 'year', 'genre', 'path']
['title', 'artist', 'album', 'year', 'genre', 'path']
);
useEffect(() => {
@ -98,7 +98,7 @@ const FolderList = () => {
const selected = folderData?.id ? folderData?.child : indexData?.child;
dispatch(
setPlayQueueByRowClick({
entries: selected.filter((entry: any) => entry.isDir === false),
entries: selected.filter((entry: any) => entry?.isDir === false),
currentIndex: rowData.index,
currentSongId: rowData.id,
uniqueSongId: rowData.uniqueId,
@ -149,8 +149,8 @@ const FolderList = () => {
header={
<GenericPageHeader
title={`${
folderData?.name
? folderData.name
folderData?.title
? folderData.title
: isLoadingFolderData
? 'Loading...'
: 'Select a folder'
@ -167,7 +167,7 @@ const FolderList = () => {
data={musicFolders}
defaultValue={musicFolder}
valueKey="id"
labelKey="name"
labelKey="title"
onChange={(e: any) => {
setMusicFolder(e);
}}

6
src/components/library/GenreList.tsx

@ -27,7 +27,7 @@ const GenreList = () => {
const res = await getGenres();
return _.orderBy(res, 'songCount', 'desc');
});
const filteredData = useSearchQuery(misc.searchQuery, genres, ['value']);
const filteredData = useSearchQuery(misc.searchQuery, genres, ['title']);
let timeout: any = null;
const handleRowClick = (e: any, rowData: any, tableData: any) => {
@ -48,12 +48,12 @@ const GenreList = () => {
const handleRowDoubleClick = (rowData: any) => {
window.clearTimeout(timeout);
timeout = null;
dispatch(setActive({ ...album.active, filter: rowData.value }));
dispatch(setActive({ ...album.active, filter: rowData.title }));
dispatch(clearSelected());
// Needs a small delay or the filter won't set properly when navigating to the album list
setTimeout(() => {
history.push(`/library/album?sortType=${rowData.value}`);
history.push(`/library/album?sortType=${rowData.title}`);
}, 50);
};

29
src/components/player/NowPlayingMiniView.tsx

@ -82,8 +82,8 @@ const NowPlayingMiniView = () => {
const genresOrderedBySongCount = _.orderBy(res, 'songCount', 'desc');
return genresOrderedBySongCount.map((genre: any) => {
return {
label: `${genre.value} (${genre.songCount})`,
value: genre.value,
label: `${genre.title} (${genre.songCount})`,
title: genre.title,
role: 'Genre',
};
});
@ -190,7 +190,7 @@ const NowPlayingMiniView = () => {
const cleanedSongs = filterPlayQueue(
config.playback.filters,
res.song.filter((song: any) => {
res.filter((song: any) => {
// Remove invalid songs that may break the player
return song.bitRate && song.duration;
})
@ -210,7 +210,7 @@ const NowPlayingMiniView = () => {
notifyToast(
'info',
getPlayedSongsNotification({
original: res.song.length,
original: res.length,
filtered: cleanedSongs.count.filtered,
type: 'play',
})
@ -224,7 +224,7 @@ const NowPlayingMiniView = () => {
notifyToast(
'info',
getPlayedSongsNotification({
original: res.song.length,
original: res.length,
filtered: cleanedSongs.count.filtered,
type: 'add',
})
@ -238,7 +238,7 @@ const NowPlayingMiniView = () => {
notifyToast(
'info',
getPlayedSongsNotification({
original: res.song.length,
original: res.length,
filtered: cleanedSongs.count.filtered,
type: 'add',
})
@ -300,7 +300,8 @@ const NowPlayingMiniView = () => {
<Whisper
ref={autoPlaylistTriggerRef}
placement="autoVertical"
trigger="none"
trigger="click"
enterable
speaker={
<StyledPopover>
<ControlLabel>How many tracks? (1-500)*</ControlLabel>
@ -356,6 +357,8 @@ const NowPlayingMiniView = () => {
container={() => genrePickerContainerRef.current}
data={!isLoadingGenres ? genres : []}
value={randomPlaylistGenre}
valueKey="title"
labelKey="label"
virtualized
onChange={(e: string) => setRandomPlaylistGenre(e)}
/>
@ -370,7 +373,7 @@ const NowPlayingMiniView = () => {
data={!isLoadingMusicFolders ? musicFolders : []}
defaultValue={musicFolder}
valueKey="id"
labelKey="name"
labelKey="title"
onChange={(e: any) => {
setMusicFolder(e);
}}
@ -411,15 +414,7 @@ const NowPlayingMiniView = () => {
</StyledPopover>
}
>
<AutoPlaylistButton
size="xs"
noText
onClick={() =>
autoPlaylistTriggerRef.current.state.isOverlayShown
? autoPlaylistTriggerRef.current.close()
: autoPlaylistTriggerRef.current.open()
}
/>
<AutoPlaylistButton size="xs" noText />
</Whisper>
<MoveTopButton
size="xs"

28
src/components/player/NowPlayingView.tsx

@ -97,8 +97,8 @@ const NowPlayingView = () => {
const genresOrderedBySongCount = _.orderBy(res, 'songCount', 'desc');
return genresOrderedBySongCount.map((genre: any) => {
return {
label: `${genre.value} (${genre.songCount})`,
value: genre.value,
label: `${genre.title} (${genre.songCount})`,
title: genre.title,
role: 'Genre',
};
});
@ -201,7 +201,7 @@ const NowPlayingView = () => {
const cleanedSongs = filterPlayQueue(
config.playback.filters,
res.song.filter((song: any) => {
res.filter((song: any) => {
// Remove invalid songs that may break the player
return song.bitRate && song.duration;
})
@ -221,7 +221,7 @@ const NowPlayingView = () => {
notifyToast(
'info',
getPlayedSongsNotification({
original: res.song.length,
original: res.length,
filtered: cleanedSongs.count.filtered,
type: 'play',
})
@ -235,7 +235,7 @@ const NowPlayingView = () => {
notifyToast(
'info',
getPlayedSongsNotification({
original: res.song.length,
original: res.length,
filtered: cleanedSongs.count.filtered,
type: 'add',
})
@ -249,7 +249,7 @@ const NowPlayingView = () => {
notifyToast(
'info',
getPlayedSongsNotification({
original: res.song.length,
original: res.length,
filtered: cleanedSongs.count.filtered,
type: 'add',
})
@ -310,7 +310,8 @@ const NowPlayingView = () => {
<Whisper
ref={autoPlaylistTriggerRef}
placement="autoVertical"
trigger="none"
trigger="click"
enterable
speaker={
<StyledPopover>
<ControlLabel>How many tracks? (1-500)*</ControlLabel>
@ -367,6 +368,8 @@ const NowPlayingView = () => {
container={() => genrePickerContainerRef.current}
data={genres}
value={randomPlaylistGenre}
valueKey="title"
labelKey="label"
virtualized
onChange={(e: string) => setRandomPlaylistGenre(e)}
/>
@ -381,7 +384,7 @@ const NowPlayingView = () => {
data={musicFolders}
defaultValue={musicFolder}
valueKey="id"
labelKey="name"
labelKey="title"
onChange={(e: any) => {
setMusicFolder(e);
}}
@ -421,14 +424,7 @@ const NowPlayingView = () => {
</StyledPopover>
}
>
<AutoPlaylistButton
size="sm"
onClick={() =>
autoPlaylistTriggerRef.current.state.isOverlayShown
? autoPlaylistTriggerRef.current.close()
: autoPlaylistTriggerRef.current.open()
}
/>
<AutoPlaylistButton size="sm" />
</Whisper>
<ButtonGroup>
<MoveTopButton

9
src/components/playlist/PlaylistList.tsx

@ -29,13 +29,12 @@ const PlaylistList = () => {
const config = useAppSelector((state) => state.config);
const misc = useAppSelector((state) => state.misc);
const playlistTriggerRef = useRef<any>();
const [sortBy] = useState('name');
const [newPlaylistName, setNewPlaylistName] = useState('');
const [viewType, setViewType] = useState(settings.getSync('playlistViewType') || 'list');
const { isLoading, isError, data: playlists, error }: any = useQuery(['playlists', sortBy], () =>
getPlaylists(sortBy)
const { isLoading, isError, data: playlists, error }: any = useQuery(['playlists'], () =>
getPlaylists()
);
const filteredData = useSearchQuery(misc.searchQuery, playlists, ['name', 'comment', 'owner']);
const filteredData = useSearchQuery(misc.searchQuery, playlists, ['title', 'comment', 'owner']);
const handleCreatePlaylist = async (name: string) => {
try {
@ -174,7 +173,7 @@ const PlaylistList = () => {
data={misc.searchQuery === '' ? playlists : filteredData}
cardTitle={{
prefix: 'playlist',
property: 'name',
property: 'title',
urlProperty: 'id',
}}
cardSubtitle={{

4
src/components/playlist/PlaylistView.tsx

@ -135,7 +135,7 @@ const PlaylistView = ({ ...rest }) => {
useEffect(() => {
// Set the local playlist data on any changes
dispatch(setPlaylistData(data?.song));
setEditName(data?.name);
setEditName(data?.title);
setEditDescription(data?.comment);
setEditPublic(data?.public);
}, [data, dispatch]);
@ -402,7 +402,7 @@ const PlaylistView = ({ ...rest }) => {
id: data.id,
}}
imageHeight={184}
title={data.name}
title={data.title}
subtitle={
<div>
<PageHeaderSubtitleDataLine $top>

4
src/components/search/SearchView.tsx

@ -164,7 +164,7 @@ const SearchView = () => {
data={data.artist}
cardTitle={{
prefix: '/library/artist',
property: 'name',
property: 'title',
urlProperty: 'id',
}}
cardSubtitle={{
@ -181,7 +181,7 @@ const SearchView = () => {
data={data.album}
cardTitle={{
prefix: '/library/album',
property: 'name',
property: 'title',
urlProperty: 'albumId',
}}
cardSubtitle={{

46
src/components/settings/ListViewColumns.ts

@ -476,7 +476,7 @@ export const albumColumnList = [
label: 'Title',
value: {
id: 'Title',
dataKey: 'name',
dataKey: 'title',
alignment: 'left',
resizable: true,
width: 300,
@ -594,7 +594,7 @@ export const albumColumnListAuto = [
label: 'Title',
value: {
id: 'Title',
dataKey: 'name',
dataKey: 'title',
alignment: 'left',
flexGrow: 5,
label: 'Title',
@ -752,7 +752,7 @@ export const playlistColumnList = [
label: 'Title',
value: {
id: 'Title',
dataKey: 'name',
dataKey: 'title',
alignment: 'left',
resizable: true,
width: 300,
@ -879,7 +879,7 @@ export const playlistColumnListAuto = [
label: 'Title',
value: {
id: 'Title',
dataKey: 'name',
dataKey: 'title',
alignment: 'left',
flexGrow: 5,
label: 'Title',
@ -956,14 +956,14 @@ export const artistColumnList = [
},
},
{
label: 'Name',
label: 'Title',
value: {
id: 'Name',
dataKey: 'name',
id: 'Title',
dataKey: 'title',
alignment: 'left',
resizable: true,
width: 300,
label: 'Name',
label: 'Title',
},
},
];
@ -1012,13 +1012,13 @@ export const artistColumnListAuto = [
},
},
{
label: 'Name',
label: 'Title',
value: {
id: 'Name',
dataKey: 'name',
id: 'Title',
dataKey: 'title',
alignment: 'left',
flexGrow: 5,
label: 'Name',
label: 'Title',
},
},
];
@ -1028,13 +1028,13 @@ export const artistColumnPicker = [
{ label: 'Album Count' },
{ label: 'CoverArt' },
{ label: 'Favorite' },
{ label: 'Name' },
{ label: 'Title' },
];
export const genreColumnPicker = [
{ label: '#' },
{ label: 'Album Count' },
{ label: 'Name' },
{ label: 'Title' },
{ label: 'Track Count' },
];
@ -1062,14 +1062,14 @@ export const genreColumnList = [
},
},
{
label: 'Name',
label: 'Title',
value: {
id: 'Name',
dataKey: 'name',
id: 'Title',
dataKey: 'title',
alignment: 'left',
resizable: true,
width: 300,
label: 'Name',
label: 'Title',
},
},
{
@ -1108,17 +1108,17 @@ export const genreColumnListAuto = [
},
},
{
label: 'Name',
label: 'Title',
value: {
id: 'Name',
dataKey: 'name',
id: 'Title',
dataKey: 'title',
alignment: 'left',
flexGrow: 5,
label: 'Name',
label: 'Title',
},
},
{
label: 'Tracks',
label: 'Track Count',
value: {
id: 'Tracks',
dataKey: 'songCount',

26
src/components/shared/ContextMenu.tsx

@ -14,8 +14,8 @@ import {
getAlbum,
getPlaylist,
deletePlaylist,
getAllArtistSongs,
getAllDirectorySongs,
getArtistSongs,
getDirectorySongs,
} from '../../api/api';
import { useAppDispatch, useAppSelector } from '../../redux/hooks';
import {
@ -120,7 +120,7 @@ export const GlobalContextMenu = () => {
const [indexToMoveTo, setIndexToMoveTo] = useState(0);
const playlistPickerContainerRef = useRef(null);
const { data: playlists }: any = useQuery(['playlists', 'name'], () => getPlaylists('name'));
const { data: playlists }: any = useQuery(['playlists'], () => getPlaylists());
const handlePlay = async () => {
dispatch(setContextMenu({ show: false }));
@ -135,7 +135,7 @@ export const GlobalContextMenu = () => {
});
for (let i = 0; i < folders.length; i += 1) {
promises.push(getAllDirectorySongs({ id: folders[i].id }));
promises.push(getDirectorySongs({ id: folders[i].id }));
}
const res = await Promise.all(promises);
@ -172,7 +172,7 @@ export const GlobalContextMenu = () => {
notifyToast('info', getPlayedSongsNotification({ ...songs.count, type: 'play' }));
} else if (misc.contextMenu.type === 'album') {
for (let i = 0; i < multiSelect.selected.length; i += 1) {
promises.push(getAlbum(multiSelect.selected[i].id));
promises.push(getAlbum({ id: multiSelect.selected[i].id }));
}
const res = await Promise.all(promises);
@ -191,7 +191,7 @@ export const GlobalContextMenu = () => {
notifyToast('info', getPlayedSongsNotification({ ...songs.count, type: 'play' }));
} else if (misc.contextMenu.type === 'artist') {
for (let i = 0; i < multiSelect.selected.length; i += 1) {
promises.push(getAllArtistSongs(multiSelect.selected[i].id));
promises.push(getArtistSongs({ id: multiSelect.selected[i].id }));
}
const res = await Promise.all(promises);
@ -223,7 +223,7 @@ export const GlobalContextMenu = () => {
});
for (let i = 0; i < folders.length; i += 1) {
promises.push(getAllDirectorySongs({ id: multiSelect.selected[i].id }));
promises.push(getDirectorySongs({ id: multiSelect.selected[i].id }));
}
const res = await Promise.all(promises);
@ -252,7 +252,7 @@ export const GlobalContextMenu = () => {
notifyToast('info', getPlayedSongsNotification({ ...songs.count, type: 'add' }));
} else if (misc.contextMenu.type === 'album') {
for (let i = 0; i < multiSelect.selected.length; i += 1) {
promises.push(getAlbum(multiSelect.selected[i].id));
promises.push(getAlbum({ id: multiSelect.selected[i].id }));
}
const res = await Promise.all(promises);
@ -266,7 +266,7 @@ export const GlobalContextMenu = () => {
notifyToast('info', getPlayedSongsNotification({ ...songs.count, type: 'add' }));
} else if (misc.contextMenu.type === 'artist') {
for (let i = 0; i < multiSelect.selected.length; i += 1) {
promises.push(getAllArtistSongs(multiSelect.selected[i].id));
promises.push(getArtistSongs({ id: multiSelect.selected[i].id }));
}
const res = await Promise.all(promises);
@ -298,7 +298,7 @@ export const GlobalContextMenu = () => {
notifyToast(
'success',
`Added ${songCount} song(s) to playlist ${
playlists.find((pl: any) => pl.id === playlistId)?.name
playlists.find((pl: any) => pl.id === playlistId)?.title
}`,
<>
<StyledButton
@ -332,7 +332,7 @@ export const GlobalContextMenu = () => {
});
for (let i = 0; i < folders.length; i += 1) {
promises.push(getAllDirectorySongs({ id: multiSelect.selected[i].id }));
promises.push(getDirectorySongs({ id: multiSelect.selected[i].id }));
}
const folderSongs = await Promise.all(promises);
@ -363,7 +363,7 @@ export const GlobalContextMenu = () => {
}
} else if (misc.contextMenu.type === 'album') {
for (let i = 0; i < multiSelect.selected.length; i += 1) {
promises.push(getAlbum(multiSelect.selected[i].id));
promises.push(getAlbum({ id: multiSelect.selected[i].id }));
}
res = await Promise.all(promises);
@ -700,7 +700,7 @@ export const GlobalContextMenu = () => {
data={playlists}
placement="autoVerticalStart"
virtualized
labelKey="name"
labelKey="title"
valueKey="id"
width={200}
onChange={(e: any) => setSelectedPlaylistId(e)}

10
src/components/starred/StarredView.tsx

@ -50,10 +50,10 @@ const StarredView = () => {
? data?.album
: data?.artist,
favorite.active.tab === 'tracks'
? ['title', 'artist', 'album', 'name', 'genre']
? ['title', 'artist', 'album', 'genre']
: favorite.active.tab === 'albums'
? ['name', 'artist', 'genre', 'year']
: ['name']
? ['title', 'artist', 'genre', 'year']
: ['title']
);
let timeout: any = null;
@ -230,7 +230,7 @@ const StarredView = () => {
data={misc.searchQuery !== '' ? filteredData : data.album}
cardTitle={{
prefix: '/library/album',
property: 'name',
property: 'title',
urlProperty: 'albumId',
}}
cardSubtitle={{
@ -279,7 +279,7 @@ const StarredView = () => {
data={misc.searchQuery !== '' ? filteredData : data.artist}
cardTitle={{
prefix: '/library/artist',
property: 'name',
property: 'title',
urlProperty: 'id',
}}
cardSubtitle={{

Loading…
Cancel
Save