Skip to content
Open
3 changes: 2 additions & 1 deletion src/plugins/touchbar/index.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import { nativeImage, type NativeImage, TouchBar } from 'electron';

import youtubeMusicIcon from '@assets/youtube-music.png?asset&asarUnpack';

import { createPlugin } from '@/utils';
import { getSongControls } from '@/providers/song-controls';
import { registerCallback, SongInfoEvent } from '@/providers/song-info';
import { t } from '@/i18n';

import youtubeMusicIcon from '@assets/youtube-music.png?asset&asarUnpack';
import { Platform } from '@/types/plugins';

export default createPlugin({
Expand Down
94 changes: 33 additions & 61 deletions src/plugins/video-toggle/button-switcher.css
Original file line number Diff line number Diff line change
Expand Up @@ -9,84 +9,56 @@
.video-toggle-custom-mode .video-switch-button {
z-index: 999;
box-sizing: border-box;
padding: 0;
margin-top: 20px;
margin-left: 10px;
background: rgba(33, 33, 33, 0.4);
border-radius: 30px;
padding: 12px;
margin: 20px 10px 0px 10px;
background: rgba(33, 33, 33, 0.7);
border-radius: 50%;
overflow: hidden;
width: 20rem;
width: 48px;
height: 48px;
text-align: center;
font-size: 18px;
letter-spacing: 1px;
color: #fff;
padding-right: 10rem;
position: absolute;
}

.video-toggle-custom-mode .video-switch-button:before {
content: attr(data-video-button-text);
position: absolute;
top: 0;
bottom: 0;
right: 0;
width: 10rem;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
z-index: 3;
pointer-events: none;
transition: all 0.2s ease;
}

.video-toggle-custom-mode .video-switch-button-checkbox {
cursor: pointer;
position: absolute;
top: 0;
left: 0;
bottom: 0;
width: 100%;
height: 100%;
opacity: 0;
z-index: 2;
.video-toggle-custom-mode .video-switch-button:hover {
background: rgba(33, 33, 33, 0.9);
transform: scale(1.1);
}

.video-toggle-custom-mode .video-switch-button-label-span {
position: relative;
.video-toggle-custom-mode .video-toggle-icon {
width: 20px;
height: 20px;
color: #fff;
stroke: currentColor;
fill: none;
pointer-events: none;
}

.video-toggle-custom-mode
.video-switch-button-checkbox:checked
+ .video-switch-button-label:before {
transform: translateX(10rem);
transition: transform 300ms linear;
.video-toggle-custom-mode #av-id {
display: none;
}

.video-toggle-custom-mode
.video-switch-button-checkbox
+ .video-switch-button-label {
position: relative;
padding: 15px 0;
display: block;
user-select: none;
pointer-events: none;
.video-toggle-custom-mode #song-video.ytmusic-player,
.video-toggle-custom-mode #song-image {
position: relative !important;
margin: auto !important;
transition: none !important;
}

.video-toggle-custom-mode
.video-switch-button-checkbox
+ .video-switch-button-label:before {
content: '';
background: rgba(60, 60, 60, 0.4);
height: 100%;
width: 100%;
position: absolute;
left: 0;
top: 0;
border-radius: 30px;
transform: translateX(0);
transition: transform 300ms;
.video-toggle-custom-mode ytmusic-player {
margin: auto 0px !important;
}

/* disable the native toggler */
.video-toggle-custom-mode #av-id {
display: none;
.video-toggle-custom-mode #song-image img {
max-width: 100% !important;
max-height: 100% !important;
object-fit: cover !important;
display: block !important;
margin: auto !important;
}
140 changes: 89 additions & 51 deletions src/plugins/video-toggle/index.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { render } from 'solid-js/web';

import { createSignal, Show } from 'solid-js';

import forceHideStyle from './force-hide.css?inline';
Expand Down Expand Up @@ -108,6 +107,7 @@ export default createPlugin({

renderer: {
config: null as VideoTogglePluginConfig | null,
setVideoVisible: null as ((visible: boolean) => void) | null,
applyStyleClass: (config: VideoTogglePluginConfig) => {
if (config.forceHide) {
document.body.classList.add('video-toggle-force-hide');
Expand All @@ -119,6 +119,7 @@ export default createPlugin({
},
async start({ getConfig }) {
const config = await getConfig();
this.config = config;
this.applyStyleClass(config);

if (config.forceHide) {
Expand Down Expand Up @@ -155,10 +156,15 @@ export default createPlugin({
},
async onPlayerApiReady(api, { getConfig }) {
const [showButton, setShowButton] = createSignal(true);
const [videoVisible, setVideoVisible] = createSignal(true);

const config = await getConfig();
this.config = config;

setVideoVisible(!config.hideVideo);

this.setVideoVisible = setVideoVisible;

const moveVolumeHud = (await window.mainConfig.plugins.isEnabled(
'precise-volume',
))
Expand All @@ -177,14 +183,11 @@ export default createPlugin({
() => (
<Show when={showButton()}>
<VideoSwitchButton
onChange={(e) => {
const target = e.target as HTMLInputElement;

setVideoState(target.checked);
initialVideoVisible={videoVisible()}
onVideoToggle={(showVideo) => {
setVideoVisible(showVideo);
setVideoState(showVideo);
}}
onClick={(e) => e.stopPropagation()}
songButtonText={t('plugins.video-toggle.templates.button-song')}
videoButtonText={t('plugins.video-toggle.templates.button-video')}
/>
</Show>
),
Expand All @@ -206,28 +209,35 @@ export default createPlugin({
}
window.mainConfig.plugins.setOptions('video-toggle', this.config);

const checkbox = document.querySelector<HTMLInputElement>(
'.video-switch-button-checkbox',
); // custom mode
if (checkbox) checkbox.checked = !this.config?.hideVideo;

if (player) {
player.style.margin = showVideo ? '' : 'auto 0px';
player.setAttribute(
'playback-mode',
showVideo ? 'OMV_PREFERRED' : 'ATV_PREFERRED',
);

document.querySelector<HTMLElement>(
const videoElement = document.querySelector<HTMLElement>(
'#song-video.ytmusic-player',
)!.style.display = showVideo ? 'block' : 'none';
document.querySelector<HTMLElement>('#song-image')!.style.display =
showVideo ? 'none' : 'block';

if (showVideo && video && !video.style.top) {
video.style.top = `${
(player.clientHeight - video.clientHeight) / 2
}px`;
);
const imageElement =
document.querySelector<HTMLElement>('#song-image');

if (videoElement && imageElement) {
if (showVideo) {
videoElement.style.display = 'block';
imageElement.style.display = 'none';

if (video && !video.style.top) {
video.style.top = `${(player.clientHeight - video.clientHeight) / 2}px`;
}
} else {
videoElement.style.display = 'none';
imageElement.style.display = 'block';

imageElement.style.position = 'relative';
imageElement.style.width = '100%';
imageElement.style.height = '100%';
imageElement.style.margin = 'auto';
}
}

moveVolumeHud(showVideo);
Expand Down Expand Up @@ -314,42 +324,70 @@ export default createPlugin({
};

if (config.mode !== 'native' && config.mode != 'disabled') {
setTimeout(() => {
const playerSelector =
document.querySelector<HTMLVideoElement>('#player');
if (!playerSelector) return;

playerSelector.prepend(switchButtonContainer);
setVideoState(!config.hideVideo);
forcePlaybackMode();
if (video) {
video.style.height = 'auto';
}
video?.addEventListener('ytmd:src-changed', videoStarted);
observeThumbnail();
videoStarted();
switch (config.align) {
case 'right': {
switchButtonContainer.style.justifyContent = 'flex-end';
return;
}
const playerSelector =
document.querySelector<HTMLVideoElement>('#player');
if (!playerSelector) return;

case 'middle': {
switchButtonContainer.style.justifyContent = 'center';
return;
}
const initializeConsistentStyling = () => {
const videoElement = document.querySelector<HTMLElement>(
'#song-video.ytmusic-player',
);
const imageElement =
document.querySelector<HTMLElement>('#song-image');

if (videoElement && imageElement) {
videoElement.style.position = 'relative';
videoElement.style.margin = 'auto';
imageElement.style.position = 'relative';
imageElement.style.margin = 'auto';
}
};

playerSelector.prepend(switchButtonContainer);
initializeConsistentStyling();
setVideoState(!config.hideVideo);
forcePlaybackMode();
if (video) {
video.style.height = 'auto';
}
video?.addEventListener('ytmd:src-changed', videoStarted);
observeThumbnail();
videoStarted();

default:
case 'left': {
switchButtonContainer.style.justifyContent = 'flex-start';
}
if (this.config) {
const container = document.getElementById(
'ytmd-video-toggle-switch-button-container',
);
if (container) {
const alignmentMap = {
right: 'flex-end',
middle: 'center',
left: 'flex-start',
};
container.style.justifyContent = alignmentMap[this.config.align];
}
}, 0);
}
}
},
onConfigChange(newConfig) {
this.config = newConfig;
this.applyStyleClass(newConfig);

const container = document.getElementById(
'ytmd-video-toggle-switch-button-container',
);
if (container) {
const alignmentMap = {
right: 'flex-end',
middle: 'center',
left: 'flex-start',
};
container.style.justifyContent = alignmentMap[newConfig.align];
}

if (this.setVideoVisible) {
this.setVideoVisible(!newConfig.hideVideo);
}
},
},
});
Loading