feat(plugin): add unobtrusive player plugin (#3104)

* feat(plugin): add unobtrusive player plugin

* fix(plugin): add removeEventListener once unobtrusive-player is disabled

* feat(plugin): prevent player page button animation when changing song

* fix(plugin): add removeEventListener for videodatachange once unobtrusive-player is disabled
This commit is contained in:
Franz DC
2025-03-26 18:36:42 +08:00
committed by GitHub
parent 77779938b9
commit 19fd0d61c6
3 changed files with 108 additions and 0 deletions

View File

@ -788,6 +788,10 @@
"description": "Integration with OBS's plugin Tuna",
"name": "Tuna OBS"
},
"unobtrusive-player": {
"description": "Prevents the player from popping up when playing a song",
"name": "Unobtrusive Player"
},
"video-toggle": {
"description": "Adds a button to switch between Video/Song mode. can also optionally remove the whole video tab",
"menu": {

View File

@ -0,0 +1,77 @@
import style from './style.css?inline';
import { createPlugin } from '@/utils';
import { t } from '@/i18n';
const handlePlay = (e: MouseEvent) => {
if (!(e.target instanceof HTMLElement)) return;
if (
e.target.closest('ytmusic-play-button-renderer') &&
!e.target.closest('ytmusic-player-page')
) {
document.body.classList.add('unobtrusive-player--did-play');
}
if (
e.target.closest('ytmusic-player-bar') &&
!document.body.classList.contains('unobtrusive-player--auto-closing')
) {
document.body.classList.remove('unobtrusive-player--did-play');
}
};
const handleVideoDataChange = () => {
const isPlayerPageOpen =
document
.querySelector('ytmusic-app-layout')
?.attributes.getNamedItem('player-ui-state')?.value ===
'PLAYER_PAGE_OPEN';
if (
document.body.classList.contains('unobtrusive-player--did-play') &&
isPlayerPageOpen
) {
document.body.classList.add('unobtrusive-player--auto-closing');
document
.querySelector<HTMLButtonElement>('.toggle-player-page-button')
?.click();
// prevent animation flickering
setTimeout(() => {
document.body.classList.remove('unobtrusive-player--auto-closing');
}, 500);
}
};
export default createPlugin({
name: () => t('plugins.unobtrusive-player.name'),
description: () => t('plugins.unobtrusive-player.description'),
restartNeeded: false,
config: {
enabled: false,
},
stylesheets: [style],
renderer: {
start: () => {
document.body.classList.add('unobtrusive-player');
document.addEventListener('click', handlePlay);
},
onPlayerApiReady: () => {
// Close player page when video changes while
// `unobtrusive-player--did-play` className is present.
document.addEventListener('videodatachange', handleVideoDataChange);
},
stop: () => {
document.removeEventListener('click', handlePlay);
document.removeEventListener('videodatachange', handleVideoDataChange);
[
'unobtrusive-player',
'unobtrusive-player--did-play',
'unobtrusive-player--auto-closing',
].forEach((className) => document.body.classList.remove(className));
},
},
});

View File

@ -0,0 +1,27 @@
body.unobtrusive-player.unobtrusive-player--did-play {
overflow: visible !important;
& ytmusic-player-page,
ytmusic-player-page * {
visibility: hidden !important;
}
& #content {
visibility: visible !important;
}
&
ytmusic-app-layout:not(.content-scrolled)
#nav-bar-background.ytmusic-app-layout,
ytmusic-app-layout:not(.content-scrolled) #nav-bar-divider.ytmusic-app-layout,
ytmusic-app-layout[is-bauhaus-sidenav-enabled][player-page-open]:not(
.content-scrolled
)
#mini-guide-background.ytmusic-app-layout {
opacity: 0 !important;
}
& .toggle-player-page-button {
transform: rotate(180deg) !important;
}
}