Skip to content

Commit a1ac3d1

Browse files
authored
feat(api-server): add insertPosition for addSongToQueue (#2808)
1 parent c21dd08 commit a1ac3d1

File tree

4 files changed

+67
-44
lines changed

4 files changed

+67
-44
lines changed

src/plugins/api-server/backend/routes/control.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -660,8 +660,8 @@ export const register = (
660660
app.openapi(routes.queueInfo, queueInfo);
661661

662662
app.openapi(routes.addSongToQueue, (ctx) => {
663-
const { videoId } = ctx.req.valid('json');
664-
controller.addSongToQueue(videoId);
663+
const { videoId, insertPosition } = ctx.req.valid('json');
664+
controller.addSongToQueue(videoId, insertPosition);
665665

666666
ctx.status(204);
667667
return ctx.body(null);

src/plugins/api-server/backend/scheme/queue.ts

+4
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@ export const QueueParamsSchema = z.object({
66

77
export const AddSongToQueueSchema = z.object({
88
videoId: z.string(),
9+
insertPosition: z
10+
.enum(['INSERT_AT_END', 'INSERT_AFTER_CURRENT_VIDEO'])
11+
.optional()
12+
.default('INSERT_AT_END'),
913
});
1014
export const MoveSongInQueueSchema = z.object({
1115
toIndex: z.number(),

src/providers/song-controls.ts

+6-2
Original file line numberDiff line numberDiff line change
@@ -97,11 +97,15 @@ export default (win: BrowserWindow) => {
9797
});
9898
},
9999
// Queue
100-
addSongToQueue: (videoId: string) => {
100+
addSongToQueue: (videoId: string, queueInsertPosition: string) => {
101101
const videoIdValue = parseStringFromArgsType(videoId);
102102
if (videoIdValue === null) return;
103103

104-
win.webContents.send('ytmd:add-to-queue', videoIdValue);
104+
win.webContents.send(
105+
'ytmd:add-to-queue',
106+
videoIdValue,
107+
queueInsertPosition,
108+
);
105109
},
106110
moveSongInQueue: (
107111
fromIndex: ArgsType<number>,

src/renderer.ts

+55-40
Original file line numberDiff line numberDiff line change
@@ -157,46 +157,61 @@ async function onApiLoaded() {
157157
} satisfies QueueResponse);
158158
});
159159

160-
window.ipcRenderer.on('ytmd:add-to-queue', (_, videoId: string) => {
161-
const queue = document.querySelector<QueueElement>('#queue');
162-
const app = document.querySelector<YouTubeMusicAppElement>('ytmusic-app');
163-
if (!app) return;
164-
165-
const store = queue?.queue.store.store;
166-
if (!store) return;
167-
168-
app.networkManager
169-
.fetch('/music/get_queue', {
170-
queueContextParams: store.getState().queue.queueContextParams,
171-
queueInsertPosition: 'INSERT_AT_END',
172-
videoIds: [videoId],
173-
})
174-
.then((result) => {
175-
if (
176-
result &&
177-
typeof result === 'object' &&
178-
'queueDatas' in result &&
179-
Array.isArray(result.queueDatas)
180-
) {
181-
queue?.dispatch({
182-
type: 'ADD_ITEMS',
183-
payload: {
184-
nextQueueItemId: store.getState().queue.nextQueueItemId,
185-
index: store.getState().queue.items.length ?? 0,
186-
items: result.queueDatas
187-
.map((it) =>
188-
typeof it === 'object' && it && 'content' in it
189-
? it.content
190-
: null,
191-
)
192-
.filter(Boolean),
193-
shuffleEnabled: false,
194-
shouldAssignIds: true,
195-
},
196-
});
197-
}
198-
});
199-
});
160+
window.ipcRenderer.on(
161+
'ytmd:add-to-queue',
162+
(_, videoId: string, queueInsertPosition: string) => {
163+
const queue = document.querySelector<QueueElement>('#queue');
164+
const app = document.querySelector<YouTubeMusicAppElement>('ytmusic-app');
165+
if (!app) return;
166+
167+
const store = queue?.queue.store.store;
168+
if (!store) return;
169+
170+
app.networkManager
171+
.fetch('/music/get_queue', {
172+
queueContextParams: store.getState().queue.queueContextParams,
173+
queueInsertPosition,
174+
videoIds: [videoId],
175+
})
176+
.then((result) => {
177+
if (
178+
result &&
179+
typeof result === 'object' &&
180+
'queueDatas' in result &&
181+
Array.isArray(result.queueDatas)
182+
) {
183+
const queueItems = store.getState().queue.items;
184+
const queueItemsLength = queueItems.length ?? 0;
185+
queue?.dispatch({
186+
type: 'ADD_ITEMS',
187+
payload: {
188+
nextQueueItemId: store.getState().queue.nextQueueItemId,
189+
index:
190+
queueInsertPosition === 'INSERT_AFTER_CURRENT_VIDEO'
191+
? queueItems.findIndex(
192+
(it) =>
193+
(
194+
it.playlistPanelVideoRenderer ||
195+
it.playlistPanelVideoWrapperRenderer
196+
?.primaryRenderer.playlistPanelVideoRenderer
197+
)?.selected,
198+
) + 1 || queueItemsLength
199+
: queueItemsLength,
200+
items: result.queueDatas
201+
.map((it) =>
202+
typeof it === 'object' && it && 'content' in it
203+
? it.content
204+
: null,
205+
)
206+
.filter(Boolean),
207+
shuffleEnabled: false,
208+
shouldAssignIds: true,
209+
},
210+
});
211+
}
212+
});
213+
},
214+
);
200215
window.ipcRenderer.on(
201216
'ytmd:move-in-queue',
202217
(_, fromIndex: number, toIndex: number) => {

0 commit comments

Comments
 (0)