import { toKeyEvent } from 'keyboardevent-from-electron-accelerator'; import keyEventAreEqual from 'keyboardevents-areequal'; import { render } from 'solid-js/web'; import { getSongMenu } from '@/providers/dom-elements'; import { isMusicOrVideoTrack } from '@/plugins/utils/renderer/check'; import { t } from '@/i18n'; import { PictureInPictureButton } from './templates/picture-in-picture-button'; import type { YoutubePlayer } from '@/types/youtube-player'; import type { PictureInPicturePluginConfig } from './index'; import type { RendererContext } from '@/types/contexts'; export const onPlayerApiReady = async ( _: YoutubePlayer, { ipc, getConfig }: RendererContext, ) => { const config = await getConfig(); const togglePictureInPicture = async () => { if ((await getConfig()).useNativePiP) { const isInPiP = document.pictureInPictureElement !== null; const video = document.querySelector('video'); const togglePiP = () => isInPiP ? document.exitPictureInPicture() : video?.requestPictureInPicture(); try { await togglePiP(); document.querySelector('#icon')?.click(); // Close the menu return true; } catch {} } ipc.send('plugin:toggle-picture-in-picture'); return false; }; if (config.hotkey) { const hotkeyEvent = toKeyEvent(config.hotkey); window.addEventListener('keydown', (event) => { if ( keyEventAreEqual(event, hotkeyEvent) && !document.querySelector( 'ytmusic-search-box', )?.opened ) { togglePictureInPicture(); } }); } const exitFullScreenButton = document.querySelector( '.exit-fullscreen-button', ); const getPlayMinimizeButton = () => document.querySelector('.player-minimize-button'); const appLayout = document.querySelector('ytmusic-app-layout'); const expandMenu = document.querySelector('#expanding-menu'); const middleControls = document.querySelector('.middle-controls'); const playerPage = document.querySelector< HTMLElement & { playerPageOpen_: boolean } >('ytmusic-player-page'); const togglePlayerPageButton = document.querySelector( '.toggle-player-page-button', ); const fullScreenButton = document.querySelector('.fullscreen-button'); const player = document.querySelector< HTMLVideoElement & { onDoubleClick_: (() => void) | undefined } >('#player'); const onPlayerDblClick = player?.onDoubleClick_; const mouseLeaveEventListener = () => middleControls?.click(); const titleBar = document.querySelector( 'nav[data-ytmd-main-panel]', ); const pipClickEventListener = async (e: Event) => { e.stopPropagation(); e.preventDefault(); await togglePictureInPicture(); }; ipc.on('ytmd:pip-toggle', (isPip: boolean) => { if (exitFullScreenButton && player) { if (isPip) { exitFullScreenButton?.addEventListener('click', pipClickEventListener); getPlayMinimizeButton()?.removeEventListener( 'click', pipClickEventListener, ); player.onDoubleClick_ = () => {}; expandMenu?.addEventListener('mouseleave', mouseLeaveEventListener); if (!playerPage?.playerPageOpen_) { togglePlayerPageButton?.click(); } fullScreenButton?.click(); appLayout?.classList.add('pip'); if (titleBar) { titleBar.style.display = 'none'; } } else { exitFullScreenButton.removeEventListener( 'click', pipClickEventListener, ); getPlayMinimizeButton()?.addEventListener( 'click', pipClickEventListener, ); player.onDoubleClick_ = onPlayerDblClick; expandMenu?.removeEventListener('mouseleave', mouseLeaveEventListener); exitFullScreenButton.click(); appLayout?.classList.remove('pip'); if (titleBar) { titleBar.style.display = 'flex'; } } } }); getPlayMinimizeButton()?.addEventListener('click', pipClickEventListener); const pipButtonContainer = document.createElement('div'); pipButtonContainer.classList.add( 'style-scope', 'menu-item', 'ytmusic-menu-popup-renderer', ); pipButtonContainer.setAttribute('aria-disabled', 'false'); pipButtonContainer.setAttribute('aria-selected', 'false'); pipButtonContainer.setAttribute('role', 'option'); pipButtonContainer.setAttribute('tabindex', '-1'); render( () => ( ), pipButtonContainer, ); const observer = new MutationObserver(() => { const menu = getSongMenu(); if (menu?.contains(pipButtonContainer) || !isMusicOrVideoTrack()) { return; } menu?.prepend(pipButtonContainer); }); observer.observe(document.querySelector('ytmusic-popup-container')!, { childList: true, subtree: true, }); };