From a1ac3d135944eb13d23489c55ca1fa2ae7e217af Mon Sep 17 00:00:00 2001 From: Franz DC Date: Wed, 1 Jan 2025 23:19:12 +0800 Subject: [PATCH] feat(api-server): add `insertPosition` for `addSongToQueue` (#2808) --- .../api-server/backend/routes/control.ts | 4 +- .../api-server/backend/scheme/queue.ts | 4 + src/providers/song-controls.ts | 8 +- src/renderer.ts | 91 +++++++++++-------- 4 files changed, 65 insertions(+), 42 deletions(-) diff --git a/src/plugins/api-server/backend/routes/control.ts b/src/plugins/api-server/backend/routes/control.ts index 0b6fc411..c2cbd8ff 100644 --- a/src/plugins/api-server/backend/routes/control.ts +++ b/src/plugins/api-server/backend/routes/control.ts @@ -660,8 +660,8 @@ export const register = ( app.openapi(routes.queueInfo, queueInfo); app.openapi(routes.addSongToQueue, (ctx) => { - const { videoId } = ctx.req.valid('json'); - controller.addSongToQueue(videoId); + const { videoId, insertPosition } = ctx.req.valid('json'); + controller.addSongToQueue(videoId, insertPosition); ctx.status(204); return ctx.body(null); diff --git a/src/plugins/api-server/backend/scheme/queue.ts b/src/plugins/api-server/backend/scheme/queue.ts index 3520885f..6096aafb 100644 --- a/src/plugins/api-server/backend/scheme/queue.ts +++ b/src/plugins/api-server/backend/scheme/queue.ts @@ -6,6 +6,10 @@ export const QueueParamsSchema = z.object({ export const AddSongToQueueSchema = z.object({ videoId: z.string(), + insertPosition: z + .enum(['INSERT_AT_END', 'INSERT_AFTER_CURRENT_VIDEO']) + .optional() + .default('INSERT_AT_END'), }); export const MoveSongInQueueSchema = z.object({ toIndex: z.number(), diff --git a/src/providers/song-controls.ts b/src/providers/song-controls.ts index dfbbc6be..c693132a 100644 --- a/src/providers/song-controls.ts +++ b/src/providers/song-controls.ts @@ -97,11 +97,15 @@ export default (win: BrowserWindow) => { }); }, // Queue - addSongToQueue: (videoId: string) => { + addSongToQueue: (videoId: string, queueInsertPosition: string) => { const videoIdValue = parseStringFromArgsType(videoId); if (videoIdValue === null) return; - win.webContents.send('ytmd:add-to-queue', videoIdValue); + win.webContents.send( + 'ytmd:add-to-queue', + videoIdValue, + queueInsertPosition, + ); }, moveSongInQueue: ( fromIndex: ArgsType, diff --git a/src/renderer.ts b/src/renderer.ts index 59bd2183..d2a06ae8 100644 --- a/src/renderer.ts +++ b/src/renderer.ts @@ -157,46 +157,61 @@ async function onApiLoaded() { } satisfies QueueResponse); }); - window.ipcRenderer.on('ytmd:add-to-queue', (_, videoId: string) => { - const queue = document.querySelector('#queue'); - const app = document.querySelector('ytmusic-app'); - if (!app) return; + window.ipcRenderer.on( + 'ytmd:add-to-queue', + (_, videoId: string, queueInsertPosition: string) => { + const queue = document.querySelector('#queue'); + const app = document.querySelector('ytmusic-app'); + if (!app) return; - const store = queue?.queue.store.store; - if (!store) return; + const store = queue?.queue.store.store; + if (!store) return; - app.networkManager - .fetch('/music/get_queue', { - queueContextParams: store.getState().queue.queueContextParams, - queueInsertPosition: 'INSERT_AT_END', - videoIds: [videoId], - }) - .then((result) => { - if ( - result && - typeof result === 'object' && - 'queueDatas' in result && - Array.isArray(result.queueDatas) - ) { - queue?.dispatch({ - type: 'ADD_ITEMS', - payload: { - nextQueueItemId: store.getState().queue.nextQueueItemId, - index: store.getState().queue.items.length ?? 0, - items: result.queueDatas - .map((it) => - typeof it === 'object' && it && 'content' in it - ? it.content - : null, - ) - .filter(Boolean), - shuffleEnabled: false, - shouldAssignIds: true, - }, - }); - } - }); - }); + app.networkManager + .fetch('/music/get_queue', { + queueContextParams: store.getState().queue.queueContextParams, + queueInsertPosition, + videoIds: [videoId], + }) + .then((result) => { + if ( + result && + typeof result === 'object' && + 'queueDatas' in result && + Array.isArray(result.queueDatas) + ) { + const queueItems = store.getState().queue.items; + const queueItemsLength = queueItems.length ?? 0; + queue?.dispatch({ + type: 'ADD_ITEMS', + payload: { + nextQueueItemId: store.getState().queue.nextQueueItemId, + index: + queueInsertPosition === 'INSERT_AFTER_CURRENT_VIDEO' + ? queueItems.findIndex( + (it) => + ( + it.playlistPanelVideoRenderer || + it.playlistPanelVideoWrapperRenderer + ?.primaryRenderer.playlistPanelVideoRenderer + )?.selected, + ) + 1 || queueItemsLength + : queueItemsLength, + items: result.queueDatas + .map((it) => + typeof it === 'object' && it && 'content' in it + ? it.content + : null, + ) + .filter(Boolean), + shuffleEnabled: false, + shouldAssignIds: true, + }, + }); + } + }); + }, + ); window.ipcRenderer.on( 'ytmd:move-in-queue', (_, fromIndex: number, toIndex: number) => {