Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
89 changes: 84 additions & 5 deletions src/renderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import type { QueueElement } from '@/types/queue';
import type { QueueResponse } from '@/types/music-player-desktop-internal';
import type { MusicPlayerAppElement } from '@/types/music-player-app-element';
import type { SearchBoxElement } from '@/types/search-box-element';
import type { RepeatMode } from '@/types/datahost-get-state';

setTheme('dark');

Expand All @@ -50,6 +51,15 @@ async function listenForApiLoad() {
}

async function onApiLoaded() {
type RepeatController = HTMLElement & {
getState: () => {
queue: {
repeatMode: RepeatMode;
};
};
onRepeatButtonClick: () => void;
};

// Workaround for macOS traffic lights
{
let osType = 'Unknown';
Expand Down Expand Up @@ -113,6 +123,72 @@ async function onApiLoaded() {
window.ipcRenderer.send('peard:get-shuffle-response', isShuffled());
});

const repeatModeOrder: RepeatMode[] = ['NONE', 'ALL', 'ONE'];

const getRepeatController = () =>
document.querySelector<RepeatController>('ytmusic-player-bar');

const getRepeatMode = () =>
getRepeatController()?.getState().queue.repeatMode;

let preferredRepeatMode = getRepeatMode();

const rememberPreferredRepeatMode = () => {
preferredRepeatMode = getRepeatMode() ?? preferredRepeatMode;
};

const switchRepeatToMode = (targetMode: RepeatMode) => {
const repeatController = getRepeatController();
if (!repeatController) {
return;
}

const currentMode = repeatController.getState().queue.repeatMode;
const currentIndex = repeatModeOrder.indexOf(currentMode);
const targetIndex = repeatModeOrder.indexOf(targetMode);
if (currentIndex < 0 || targetIndex < 0) {
return;
}

const repeatSwitches =
(targetIndex - currentIndex + repeatModeOrder.length) %
repeatModeOrder.length;
for (let i = 0; i < repeatSwitches; i++) {
repeatController.onRepeatButtonClick();
}
};

document.addEventListener(
'click',
(event) => {
if (
event.target instanceof Element &&
event.target.closest('#right-controls .repeat')
) {
window.setTimeout(rememberPreferredRepeatMode, 0);
}
},
{ capture: true },
);

document.addEventListener('videodatachange', (event) => {
const { detail } = event;
if (detail?.name !== 'dataloaded') {
return;
}

const modeToRestore = preferredRepeatMode;
if (!modeToRestore || modeToRestore === 'NONE') {
return;
}

window.setTimeout(() => {
if (getRepeatMode() === 'NONE') {
switchRepeatToMode(modeToRestore);
}
}, 350);
});

window.ipcRenderer.on(
'peard:update-like',
(_, status: 'LIKE' | 'DISLIKE' = 'LIKE') => {
Expand All @@ -124,13 +200,16 @@ async function onApiLoaded() {
},
);
window.ipcRenderer.on('peard:switch-repeat', (_, repeat = 1) => {
const repeatController = getRepeatController();
if (!repeatController) {
return;
}

for (let i = 0; i < repeat; i++) {
document
.querySelector<
HTMLElement & { onRepeatButtonClick: () => void }
>('ytmusic-player-bar')
?.onRepeatButtonClick();
repeatController.onRepeatButtonClick();
}

rememberPreferredRepeatMode();
});
window.ipcRenderer.on('peard:update-volume', (_, volume: number) => {
document
Expand Down