Replace startScan (full library refresh) with refreshItem (individual item refresh) for jellyfin metadata editing

This commit is contained in:
ChrisScott9456
2026-06-28 20:19:12 -04:00
parent aa12585b20
commit 56f05ddafc
7 changed files with 32 additions and 29 deletions
+3 -3
View File
@@ -864,15 +864,15 @@ export const controller: GeneralController = {
server.type,
)?.(addContext({ ...args, apiClientProps: { ...args.apiClientProps, server } }));
},
startScan(args) {
refreshItems(args) {
const server = getServerById(args.apiClientProps.serverId);
if (!server) {
throw new Error(`${i18n.t('error.apiRouteError')}: startScan`);
throw new Error(`${i18n.t('error.apiRouteError')}: refreshItems`);
}
return apiController(
'startScan',
'refreshItems',
server.type,
)?.(addContext({ ...args, apiClientProps: { ...args.apiClientProps, server } }));
},
+5 -3
View File
@@ -365,11 +365,13 @@ export const contract = c.router({
400: jfType._response.error,
},
},
startScan: {
refreshItem: {
body: z.null(),
method: 'POST',
path: 'Library/Refresh',
query: z.object({}),
path: 'Items/:id/Refresh',
query: z.object({
MetadataRefreshMode: z.string().optional(),
}),
responses: {
204: z.null(),
400: jfType._response.error,
@@ -1931,17 +1931,18 @@ export const JellyfinController: InternalControllerEndpoint = {
return null;
},
startScan: async (args) => {
const { apiClientProps } = args;
refreshItems: async (args) => {
const { apiClientProps, query } = args;
const res = await jfApiClient(apiClientProps).startScan({
body: null,
query: {},
});
if (res.status !== 204) {
throw new Error('Failed to start scan');
}
await Promise.all(
query.ids.map((id) =>
jfApiClient(apiClientProps).refreshItem({
body: null,
params: { id },
query: { MetadataRefreshMode: 'FullRefresh' },
}),
),
);
return null;
},
@@ -1261,7 +1261,7 @@ export const NavidromeController: InternalControllerEndpoint = {
id: res.body.data.id,
};
},
startScan: SubsonicController.startScan,
refreshItems: SubsonicController.refreshItems,
updateInternetRadioStation: async (args) => {
const { apiClientProps, body, query } = args;
@@ -2461,7 +2461,7 @@ export const SubsonicController: InternalControllerEndpoint = {
return null;
},
startScan: async (args) => {
refreshItems: async (args) => {
const { apiClientProps } = args;
const res = await ssApiClient(apiClientProps).startScan({ query: {} });
@@ -2470,7 +2470,7 @@ export const SubsonicController: InternalControllerEndpoint = {
throw new Error('Failed to start scan');
}
return res.body.scanStatus;
return null;
},
updateInternetRadioStation: async (args) => {
const { apiClientProps, body, query } = args;
@@ -286,7 +286,10 @@ export const useMetadataEditor = ({ browser, songs: songsProp, utils }: UseMetad
if (rescan && server) {
try {
await controller.startScan({ apiClientProps: { serverId: server.id } });
await controller.refreshItems({
apiClientProps: { serverId: server.id },
query: { ids: resolvedSongs.map((s) => s.id) },
});
toast.success({ message: t('page.itemDetail.rescanStarted') });
} catch {
// non-fatal
+6 -9
View File
@@ -1418,14 +1418,9 @@ export type SearchSongsQuery = {
songStartIndex?: number;
};
export type StartScanArgs = BaseEndpointArgs;
export type RefreshItemsArgs = BaseEndpointArgs & { query: { ids: string[] } };
export type StartScanResponse = null | {
count: number;
folderCount: number;
lastScan?: string;
scanning: boolean;
};
export type RefreshItemsResponse = null;
export type SynchronizedLyricsArray = Array<[number, string]>;
@@ -1532,6 +1527,7 @@ export type ControllerEndpoint = {
getUserInfo: (args: UserInfoArgs) => Promise<UserInfoResponse>;
getUserList?: (args: UserListArgs) => Promise<UserListResponse>;
movePlaylistItem?: (args: MoveItemArgs) => Promise<void>;
refreshItems: (args: RefreshItemsArgs) => Promise<RefreshItemsResponse>;
removeFromPlaylist: (args: RemoveFromPlaylistArgs) => Promise<RemoveFromPlaylistResponse>;
replacePlaylist: (args: ReplacePlaylistArgs) => Promise<ReplacePlaylistResponse>;
savePlayQueue: (args: SaveQueueArgs) => Promise<void>;
@@ -1540,7 +1536,6 @@ export type ControllerEndpoint = {
setPlaylistSongs: (args: SetPlaylistSongsArgs) => Promise<SetPlaylistSongsResponse>;
setRating?: (args: SetRatingArgs) => Promise<RatingResponse>;
shareItem?: (args: ShareItemArgs) => Promise<ShareItemResponse>;
startScan: (args: StartScanArgs) => Promise<StartScanResponse>;
updateInternetRadioStation: (
args: UpdateInternetRadioStationArgs,
) => Promise<UpdateInternetRadioStationResponse>;
@@ -1695,6 +1690,9 @@ export type InternalControllerEndpoint = {
getUserInfo: (args: ReplaceApiClientProps<UserInfoArgs>) => Promise<UserInfoResponse>;
getUserList?: (args: ReplaceApiClientProps<UserListArgs>) => Promise<UserListResponse>;
movePlaylistItem?: (args: ReplaceApiClientProps<MoveItemArgs>) => Promise<void>;
refreshItems: (
args: ReplaceApiClientProps<RefreshItemsArgs>,
) => Promise<RefreshItemsResponse>;
removeFromPlaylist: (
args: ReplaceApiClientProps<RemoveFromPlaylistArgs>,
) => Promise<RemoveFromPlaylistResponse>;
@@ -1709,7 +1707,6 @@ export type InternalControllerEndpoint = {
) => Promise<SetPlaylistSongsResponse>;
setRating?: (args: ReplaceApiClientProps<SetRatingArgs>) => Promise<RatingResponse>;
shareItem?: (args: ReplaceApiClientProps<ShareItemArgs>) => Promise<ShareItemResponse>;
startScan: (args: ReplaceApiClientProps<StartScanArgs>) => Promise<StartScanResponse>;
updateInternetRadioStation: (
args: ReplaceApiClientProps<UpdateInternetRadioStationArgs>,
) => Promise<UpdateInternetRadioStationResponse>;