feat(api-server): add insertPosition for addSongToQueue (#2808)

This commit is contained in:
Franz DC
2025-01-01 23:19:12 +08:00
committed by GitHub
parent c21dd08a40
commit a1ac3d1359
4 changed files with 65 additions and 42 deletions

View File

@ -660,8 +660,8 @@ export const register = (
app.openapi(routes.queueInfo, queueInfo); app.openapi(routes.queueInfo, queueInfo);
app.openapi(routes.addSongToQueue, (ctx) => { app.openapi(routes.addSongToQueue, (ctx) => {
const { videoId } = ctx.req.valid('json'); const { videoId, insertPosition } = ctx.req.valid('json');
controller.addSongToQueue(videoId); controller.addSongToQueue(videoId, insertPosition);
ctx.status(204); ctx.status(204);
return ctx.body(null); return ctx.body(null);

View File

@ -6,6 +6,10 @@ export const QueueParamsSchema = z.object({
export const AddSongToQueueSchema = z.object({ export const AddSongToQueueSchema = z.object({
videoId: z.string(), videoId: z.string(),
insertPosition: z
.enum(['INSERT_AT_END', 'INSERT_AFTER_CURRENT_VIDEO'])
.optional()
.default('INSERT_AT_END'),
}); });
export const MoveSongInQueueSchema = z.object({ export const MoveSongInQueueSchema = z.object({
toIndex: z.number(), toIndex: z.number(),

View File

@ -97,11 +97,15 @@ export default (win: BrowserWindow) => {
}); });
}, },
// Queue // Queue
addSongToQueue: (videoId: string) => { addSongToQueue: (videoId: string, queueInsertPosition: string) => {
const videoIdValue = parseStringFromArgsType(videoId); const videoIdValue = parseStringFromArgsType(videoId);
if (videoIdValue === null) return; if (videoIdValue === null) return;
win.webContents.send('ytmd:add-to-queue', videoIdValue); win.webContents.send(
'ytmd:add-to-queue',
videoIdValue,
queueInsertPosition,
);
}, },
moveSongInQueue: ( moveSongInQueue: (
fromIndex: ArgsType<number>, fromIndex: ArgsType<number>,

View File

@ -157,46 +157,61 @@ async function onApiLoaded() {
} satisfies QueueResponse); } satisfies QueueResponse);
}); });
window.ipcRenderer.on('ytmd:add-to-queue', (_, videoId: string) => { window.ipcRenderer.on(
const queue = document.querySelector<QueueElement>('#queue'); 'ytmd:add-to-queue',
const app = document.querySelector<YouTubeMusicAppElement>('ytmusic-app'); (_, videoId: string, queueInsertPosition: string) => {
if (!app) return; const queue = document.querySelector<QueueElement>('#queue');
const app = document.querySelector<YouTubeMusicAppElement>('ytmusic-app');
if (!app) return;
const store = queue?.queue.store.store; const store = queue?.queue.store.store;
if (!store) return; if (!store) return;
app.networkManager app.networkManager
.fetch('/music/get_queue', { .fetch('/music/get_queue', {
queueContextParams: store.getState().queue.queueContextParams, queueContextParams: store.getState().queue.queueContextParams,
queueInsertPosition: 'INSERT_AT_END', queueInsertPosition,
videoIds: [videoId], videoIds: [videoId],
}) })
.then((result) => { .then((result) => {
if ( if (
result && result &&
typeof result === 'object' && typeof result === 'object' &&
'queueDatas' in result && 'queueDatas' in result &&
Array.isArray(result.queueDatas) Array.isArray(result.queueDatas)
) { ) {
queue?.dispatch({ const queueItems = store.getState().queue.items;
type: 'ADD_ITEMS', const queueItemsLength = queueItems.length ?? 0;
payload: { queue?.dispatch({
nextQueueItemId: store.getState().queue.nextQueueItemId, type: 'ADD_ITEMS',
index: store.getState().queue.items.length ?? 0, payload: {
items: result.queueDatas nextQueueItemId: store.getState().queue.nextQueueItemId,
.map((it) => index:
typeof it === 'object' && it && 'content' in it queueInsertPosition === 'INSERT_AFTER_CURRENT_VIDEO'
? it.content ? queueItems.findIndex(
: null, (it) =>
) (
.filter(Boolean), it.playlistPanelVideoRenderer ||
shuffleEnabled: false, it.playlistPanelVideoWrapperRenderer
shouldAssignIds: true, ?.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( window.ipcRenderer.on(
'ytmd:move-in-queue', 'ytmd:move-in-queue',
(_, fromIndex: number, toIndex: number) => { (_, fromIndex: number, toIndex: number) => {