mirror of
https://github.com/jeffvli/feishin.git
synced 2026-07-16 23:50:17 +02:00
Improve Jellyfin playlist loading and modification performance times (#2184)
* Remove unneeded Fields from getPlaylistSongList * Add optimized controller function for playlist addition duplication checks * Remove Jellyfin People data handling * move artist map inline --------- Co-authored-by: Kendall Garner <17521368+kgarner7@users.noreply.github.com>
This commit is contained in:
@@ -546,6 +546,18 @@ export const controller: GeneralController = {
|
||||
server.type,
|
||||
)?.(addContext({ ...args, apiClientProps: { ...args.apiClientProps, server } }));
|
||||
},
|
||||
getPlaylistSongIds(args) {
|
||||
const server = getServerById(args.apiClientProps.serverId);
|
||||
|
||||
if (!server) {
|
||||
throw new Error(`${i18n.t('error.apiRouteError')}: getPlaylistSongIds`);
|
||||
}
|
||||
|
||||
return apiController(
|
||||
'getPlaylistSongIds',
|
||||
server.type,
|
||||
)?.(addContext({ ...args, apiClientProps: { ...args.apiClientProps, server } }));
|
||||
},
|
||||
getPlaylistSongList(args) {
|
||||
const server = getServerById(args.apiClientProps.serverId);
|
||||
|
||||
|
||||
@@ -197,8 +197,8 @@ const JF_FIELDS = {
|
||||
'SortName',
|
||||
'ProviderIds',
|
||||
],
|
||||
ALBUM_DETAIL: ['Genres', 'DateCreated', 'ChildCount', 'People', 'Tags', 'ProviderIds'],
|
||||
ALBUM_LIST: ['People', 'Tags', 'Studios', 'SortName', 'ProviderIds', 'ChildCount'],
|
||||
ALBUM_DETAIL: ['Genres', 'DateCreated', 'ChildCount', 'Tags', 'ProviderIds'],
|
||||
ALBUM_LIST: ['Tags', 'Studios', 'SortName', 'ProviderIds', 'ChildCount'],
|
||||
FOLDER: ['Genres', 'DateCreated', 'MediaSources', 'ParentId'],
|
||||
GENRE: ['ItemCounts'],
|
||||
PLAYLIST_DETAIL: [
|
||||
@@ -210,16 +210,7 @@ const JF_FIELDS = {
|
||||
'SortName',
|
||||
],
|
||||
PLAYLIST_LIST: ['ChildCount', 'Genres', 'DateCreated', 'ParentId', 'Overview'],
|
||||
SONG: [
|
||||
'Genres',
|
||||
'DateCreated',
|
||||
'MediaSources',
|
||||
'ParentId',
|
||||
'People',
|
||||
'Tags',
|
||||
'SortName',
|
||||
'ProviderIds',
|
||||
],
|
||||
SONG: ['Genres', 'DateCreated', 'MediaSources', 'ParentId', 'Tags', 'SortName', 'ProviderIds'],
|
||||
} as const;
|
||||
|
||||
export const JellyfinController: InternalControllerEndpoint = {
|
||||
@@ -1056,6 +1047,35 @@ export const JellyfinController: InternalControllerEndpoint = {
|
||||
apiClientProps,
|
||||
query: { ...query, limit: 1, startIndex: 0 },
|
||||
}).then((result) => result!.totalRecordCount!),
|
||||
getPlaylistSongIds: async (args) => {
|
||||
const { apiClientProps, query } = args;
|
||||
|
||||
if (!apiClientProps.server?.userId) {
|
||||
throw new Error('No userId found');
|
||||
}
|
||||
|
||||
const res = await jfApiClient(apiClientProps).getPlaylistSongList({
|
||||
params: {
|
||||
id: query.id,
|
||||
},
|
||||
query: {
|
||||
// XXX: No fields are required for only IDs, which saves processing time between
|
||||
// the Jellyfin server query, network (MBs vs KBs), and in-app parsing.
|
||||
IncludeItemTypes: 'Audio',
|
||||
UserId: apiClientProps.server?.userId,
|
||||
},
|
||||
});
|
||||
|
||||
if (res.status !== 200) {
|
||||
throw new Error('Failed to get playlist song list IDs');
|
||||
}
|
||||
|
||||
return {
|
||||
items: res.body.Items.map((item) => item.Id),
|
||||
startIndex: 0,
|
||||
totalRecordCount: res.body.TotalRecordCount,
|
||||
};
|
||||
},
|
||||
getPlaylistSongList: async (args) => {
|
||||
const { apiClientProps, query } = args;
|
||||
|
||||
@@ -1068,7 +1088,7 @@ export const JellyfinController: InternalControllerEndpoint = {
|
||||
id: query.id,
|
||||
},
|
||||
query: {
|
||||
Fields: JF_FIELDS.SONG,
|
||||
Fields: JF_FIELDS.PLAYLIST_DETAIL,
|
||||
IncludeItemTypes: 'Audio',
|
||||
UserId: apiClientProps.server?.userId,
|
||||
},
|
||||
|
||||
@@ -663,6 +663,11 @@ export const NavidromeController: InternalControllerEndpoint = {
|
||||
apiClientProps,
|
||||
query: { ...query, limit: 1, startIndex: 0 },
|
||||
}).then((result) => result!.totalRecordCount!),
|
||||
getPlaylistSongIds: async (args) =>
|
||||
NavidromeController.getPlaylistSongList(args).then((result) => ({
|
||||
...result,
|
||||
items: result.items.map((song) => song.id),
|
||||
})),
|
||||
getPlaylistSongList: async (args: PlaylistSongListArgs): Promise<PlaylistSongListResponse> => {
|
||||
const { apiClientProps, query } = args;
|
||||
|
||||
|
||||
@@ -338,6 +338,9 @@ export const queryKeys: Record<
|
||||
|
||||
return [serverId, 'playlists', 'songList'] as const;
|
||||
},
|
||||
songListIds: (serverId: string, id: string) => {
|
||||
return [serverId, 'playlists', 'songListIds', id] as const;
|
||||
},
|
||||
},
|
||||
radio: {
|
||||
list: (serverId: string) => [serverId, 'radio', 'list'] as const,
|
||||
|
||||
@@ -1229,6 +1229,11 @@ export const SubsonicController: InternalControllerEndpoint = {
|
||||
|
||||
return results.length;
|
||||
},
|
||||
getPlaylistSongIds: async (args) =>
|
||||
SubsonicController.getPlaylistSongList(args).then((result) => ({
|
||||
...result,
|
||||
items: result.items.map((song) => song.id),
|
||||
})),
|
||||
getPlaylistSongList: async ({ apiClientProps, query }) => {
|
||||
const res = await ssApiClient(apiClientProps).getPlaylist({
|
||||
query: {
|
||||
|
||||
Reference in New Issue
Block a user