mirror of
https://github.com/th-ch/youtube-music.git
synced 2026-01-10 18:21:47 +00:00
feat(api-server): add endpoint to get shuffle state (#2792)
This commit is contained in:
@ -173,7 +173,24 @@ const routes = {
|
||||
},
|
||||
},
|
||||
}),
|
||||
|
||||
getShuffleState: createRoute({
|
||||
method: 'get',
|
||||
path: `/api/${API_VERSION}/shuffle`,
|
||||
summary: 'get shuffle state',
|
||||
description: 'Get the current shuffle state',
|
||||
responses: {
|
||||
200: {
|
||||
description: 'Success',
|
||||
content: {
|
||||
'application/json': {
|
||||
schema: z.object({
|
||||
state: z.boolean().nullable(),
|
||||
}),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}),
|
||||
shuffle: createRoute({
|
||||
method: 'post',
|
||||
path: `/api/${API_VERSION}/shuffle`,
|
||||
@ -581,6 +598,25 @@ export const register = (
|
||||
ctx.status(204);
|
||||
return ctx.body(null);
|
||||
});
|
||||
|
||||
app.openapi(routes.getShuffleState, async (ctx) => {
|
||||
const stateResponsePromise = new Promise<boolean>((resolve) => {
|
||||
ipcMain.once(
|
||||
'ytmd:get-shuffle-response',
|
||||
(_, isShuffled: boolean | undefined) => {
|
||||
return resolve(!!isShuffled);
|
||||
},
|
||||
);
|
||||
|
||||
controller.requestShuffleInformation();
|
||||
});
|
||||
|
||||
const isShuffled = await stateResponsePromise;
|
||||
|
||||
ctx.status(200);
|
||||
return ctx.json({ state: isShuffled });
|
||||
});
|
||||
|
||||
app.openapi(routes.shuffle, (ctx) => {
|
||||
controller.shuffle();
|
||||
|
||||
|
||||
2
src/plugins/shortcuts/mpris-service.d.ts
vendored
2
src/plugins/shortcuts/mpris-service.d.ts
vendored
@ -86,7 +86,7 @@ declare module '@jellybrick/mpris-service' {
|
||||
supportedMimeTypes: string[];
|
||||
canQuit: boolean;
|
||||
canRaise: boolean;
|
||||
canSetFullscreen?: boolean;
|
||||
canUsePlayerControls?: boolean;
|
||||
desktopEntry?: string;
|
||||
hasTrackList: boolean;
|
||||
|
||||
|
||||
@ -77,7 +77,7 @@ function setupMPRIS() {
|
||||
|
||||
instance.canRaise = true;
|
||||
instance.canQuit = false;
|
||||
instance.canSetFullscreen = true;
|
||||
instance.canUsePlayerControls = true;
|
||||
instance.supportedUriSchemes = ['http', 'https'];
|
||||
instance.desktopEntry = 'youtube-music';
|
||||
return instance;
|
||||
@ -93,6 +93,7 @@ function registerMPRIS(win: BrowserWindow) {
|
||||
shuffle,
|
||||
switchRepeat,
|
||||
setFullscreen,
|
||||
requestShuffleInformation,
|
||||
requestFullscreenInformation,
|
||||
requestQueueInformation,
|
||||
} = songControls;
|
||||
@ -126,8 +127,10 @@ function registerMPRIS(win: BrowserWindow) {
|
||||
win.webContents.send('ytmd:setup-time-changed-listener', 'mpris');
|
||||
win.webContents.send('ytmd:setup-repeat-changed-listener', 'mpris');
|
||||
win.webContents.send('ytmd:setup-volume-changed-listener', 'mpris');
|
||||
win.webContents.send('ytmd:setup-shuffle-changed-listener', 'mpris');
|
||||
win.webContents.send('ytmd:setup-fullscreen-changed-listener', 'mpris');
|
||||
win.webContents.send('ytmd:setup-autoplay-changed-listener', 'mpris');
|
||||
requestShuffleInformation();
|
||||
requestFullscreenInformation();
|
||||
requestQueueInformation();
|
||||
});
|
||||
@ -156,8 +159,16 @@ function registerMPRIS(win: BrowserWindow) {
|
||||
requestQueueInformation();
|
||||
});
|
||||
|
||||
ipcMain.on('ytmd:shuffle-changed', (_, shuffleEnabled: boolean) => {
|
||||
if (player.shuffle === undefined || !player.canUsePlayerControls) {
|
||||
return;
|
||||
}
|
||||
|
||||
player.shuffle = shuffleEnabled ?? !player.shuffle;
|
||||
});
|
||||
|
||||
ipcMain.on('ytmd:fullscreen-changed', (_, changedTo: boolean) => {
|
||||
if (player.fullscreen === undefined || !player.canSetFullscreen) {
|
||||
if (player.fullscreen === undefined || !player.canUsePlayerControls) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -168,7 +179,7 @@ function registerMPRIS(win: BrowserWindow) {
|
||||
ipcMain.on(
|
||||
'ytmd:set-fullscreen',
|
||||
(_, isFullscreen: boolean | undefined) => {
|
||||
if (!player.canSetFullscreen || isFullscreen === undefined) {
|
||||
if (!player.canUsePlayerControls || isFullscreen === undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -179,7 +190,7 @@ function registerMPRIS(win: BrowserWindow) {
|
||||
ipcMain.on(
|
||||
'ytmd:fullscreen-changed-supported',
|
||||
(_, isFullscreenSupported: boolean) => {
|
||||
player.canSetFullscreen = isFullscreenSupported;
|
||||
player.canUsePlayerControls = isFullscreenSupported;
|
||||
},
|
||||
);
|
||||
ipcMain.on('ytmd:autoplay-changed', (_) => {
|
||||
@ -272,6 +283,12 @@ function registerMPRIS(win: BrowserWindow) {
|
||||
player.on('position', seekTo);
|
||||
|
||||
player.on('shuffle', (enableShuffle) => {
|
||||
if (!player.canUsePlayerControls || enableShuffle === undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
player.shuffle = enableShuffle;
|
||||
|
||||
if (enableShuffle) {
|
||||
shuffle();
|
||||
requestQueueInformation();
|
||||
|
||||
@ -62,6 +62,9 @@ export default (win: BrowserWindow) => {
|
||||
win.webContents.send('ytmd:seek-by', seconds);
|
||||
}
|
||||
},
|
||||
requestShuffleInformation: () => {
|
||||
win.webContents.send('ytmd:get-shuffle');
|
||||
},
|
||||
shuffle: () => win.webContents.send('ytmd:shuffle'),
|
||||
switchRepeat: (n: ArgsType<number> = 1) => {
|
||||
const repeat = parseNumberFromArgsType(n);
|
||||
|
||||
@ -87,6 +87,28 @@ export const setupVolumeChangedListener = singleton((api: YoutubePlayer) => {
|
||||
window.ipcRenderer.send('ytmd:volume-changed', api.getVolume());
|
||||
});
|
||||
|
||||
export const setupShuffleChangedListener = singleton(() => {
|
||||
const playerBar = document.querySelector('ytmusic-player-bar');
|
||||
|
||||
if (!playerBar) {
|
||||
window.ipcRenderer.send('ytmd:shuffle-changed-supported', false);
|
||||
return;
|
||||
}
|
||||
|
||||
const observer = new MutationObserver(() => {
|
||||
window.ipcRenderer.send(
|
||||
'ytmd:shuffle-changed',
|
||||
(playerBar?.attributes.getNamedItem('shuffle-on') ?? null) !== null,
|
||||
);
|
||||
});
|
||||
|
||||
observer.observe(playerBar, {
|
||||
attributes: true,
|
||||
childList: false,
|
||||
subtree: false,
|
||||
});
|
||||
});
|
||||
|
||||
export const setupFullScreenChangedListener = singleton(() => {
|
||||
const playerBar = document.querySelector('ytmusic-player-bar');
|
||||
|
||||
@ -139,6 +161,10 @@ export default (api: YoutubePlayer) => {
|
||||
setupVolumeChangedListener(api);
|
||||
});
|
||||
|
||||
window.ipcRenderer.on('ytmd:setup-shuffle-changed-listener', () => {
|
||||
setupShuffleChangedListener();
|
||||
});
|
||||
|
||||
window.ipcRenderer.on('ytmd:setup-fullscreen-changed-listener', () => {
|
||||
setupFullScreenChangedListener();
|
||||
});
|
||||
|
||||
@ -80,6 +80,20 @@ async function onApiLoaded() {
|
||||
>('ytmusic-player-bar')
|
||||
?.queue.shuffle();
|
||||
});
|
||||
|
||||
const isShuffled = () => {
|
||||
const isShuffled =
|
||||
document
|
||||
.querySelector<HTMLElement>('ytmusic-player-bar')
|
||||
?.attributes.getNamedItem('shuffle-on') ?? null;
|
||||
|
||||
return isShuffled !== null;
|
||||
};
|
||||
|
||||
window.ipcRenderer.on('ytmd:get-shuffle', () => {
|
||||
window.ipcRenderer.send('ytmd:get-shuffle-response', isShuffled());
|
||||
});
|
||||
|
||||
window.ipcRenderer.on(
|
||||
'ytmd:update-like',
|
||||
(_, status: 'LIKE' | 'DISLIKE' = 'LIKE') => {
|
||||
|
||||
Reference in New Issue
Block a user