mirror of
https://github.com/th-ch/youtube-music.git
synced 2026-01-12 11:01:45 +00:00
feat: run prettier
This commit is contained in:
@ -13,13 +13,10 @@ export default createPlugin({
|
||||
description: 'gives menu-bars a fancy, dark or album-color look',
|
||||
restartNeeded: true,
|
||||
config: {
|
||||
enabled: (
|
||||
typeof window !== 'undefined' &&
|
||||
!window.navigator?.userAgent?.includes('mac')
|
||||
) || (
|
||||
typeof global !== 'undefined' &&
|
||||
global.process?.platform !== 'darwin'
|
||||
),
|
||||
enabled:
|
||||
(typeof window !== 'undefined' &&
|
||||
!window.navigator?.userAgent?.includes('mac')) ||
|
||||
(typeof global !== 'undefined' && global.process?.platform !== 'darwin'),
|
||||
hideDOMWindowControls: false,
|
||||
} as InAppMenuConfig,
|
||||
stylesheets: [titlebarStyle],
|
||||
@ -31,4 +28,3 @@ export default createPlugin({
|
||||
onPlayerApiReady,
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
@ -5,7 +5,10 @@ import { BrowserWindow, Menu, MenuItem, ipcMain, nativeImage } from 'electron';
|
||||
import type { BackendContext } from '@/types/contexts';
|
||||
import type { InAppMenuConfig } from './index';
|
||||
|
||||
export const onMainLoad = ({ window: win, ipc: { handle, send } }: BackendContext<InAppMenuConfig>) => {
|
||||
export const onMainLoad = ({
|
||||
window: win,
|
||||
ipc: { handle, send },
|
||||
}: BackendContext<InAppMenuConfig>) => {
|
||||
win.on('close', () => {
|
||||
send('close-all-in-app-menu-panel');
|
||||
});
|
||||
@ -16,11 +19,13 @@ export const onMainLoad = ({ window: win, ipc: { handle, send } }: BackendContex
|
||||
});
|
||||
});
|
||||
|
||||
handle(
|
||||
'get-menu',
|
||||
() => JSON.parse(JSON.stringify(
|
||||
Menu.getApplicationMenu(),
|
||||
(key: string, value: unknown) => (key !== 'commandsMap' && key !== 'menu') ? value : undefined),
|
||||
handle('get-menu', () =>
|
||||
JSON.parse(
|
||||
JSON.stringify(
|
||||
Menu.getApplicationMenu(),
|
||||
(key: string, value: unknown) =>
|
||||
key !== 'commandsMap' && key !== 'menu' ? value : undefined,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
@ -28,7 +33,7 @@ export const onMainLoad = ({ window: win, ipc: { handle, send } }: BackendContex
|
||||
const menu = Menu.getApplicationMenu();
|
||||
|
||||
let target: MenuItem | null = null;
|
||||
const stack = [...menu?.items ?? []];
|
||||
const stack = [...(menu?.items ?? [])];
|
||||
while (stack.length > 0) {
|
||||
const now = stack.shift();
|
||||
now?.submenu?.items.forEach((item) => stack.push(item));
|
||||
@ -44,15 +49,21 @@ export const onMainLoad = ({ window: win, ipc: { handle, send } }: BackendContex
|
||||
|
||||
ipcMain.handle('menu-event', (event, commandId: number) => {
|
||||
const target = getMenuItemById(commandId);
|
||||
if (target) target.click(undefined, BrowserWindow.fromWebContents(event.sender), event.sender);
|
||||
if (target)
|
||||
target.click(
|
||||
undefined,
|
||||
BrowserWindow.fromWebContents(event.sender),
|
||||
event.sender,
|
||||
);
|
||||
});
|
||||
|
||||
handle('get-menu-by-id', (commandId: number) => {
|
||||
const result = getMenuItemById(commandId);
|
||||
|
||||
return JSON.parse(JSON.stringify(
|
||||
result,
|
||||
(key: string, value: unknown) => (key !== 'commandsMap' && key !== 'menu') ? value : undefined),
|
||||
return JSON.parse(
|
||||
JSON.stringify(result, (key: string, value: unknown) =>
|
||||
key !== 'commandsMap' && key !== 'menu' ? value : undefined,
|
||||
),
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
@ -4,7 +4,10 @@ import type { InAppMenuConfig } from './index';
|
||||
import type { MenuContext } from '@/types/contexts';
|
||||
import type { MenuTemplate } from '@/menu';
|
||||
|
||||
export const onMenu = async ({ getConfig, setConfig }: MenuContext<InAppMenuConfig>): Promise<MenuTemplate> => {
|
||||
export const onMenu = async ({
|
||||
getConfig,
|
||||
setConfig,
|
||||
}: MenuContext<InAppMenuConfig>): Promise<MenuTemplate> => {
|
||||
const config = await getConfig();
|
||||
|
||||
if (is.linux()) {
|
||||
@ -16,8 +19,8 @@ export const onMenu = async ({ getConfig, setConfig }: MenuContext<InAppMenuConf
|
||||
click(item) {
|
||||
config.hideDOMWindowControls = item.checked;
|
||||
setConfig(config);
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
@ -1,9 +1,13 @@
|
||||
const Icons = {
|
||||
submenu: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none" /><polyline points="9 6 15 12 9 18" /></svg>',
|
||||
checkbox: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><path d="M5 12l5 5l10 -10" /></svg>',
|
||||
submenu:
|
||||
'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none" /><polyline points="9 6 15 12 9 18" /></svg>',
|
||||
checkbox:
|
||||
'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><path d="M5 12l5 5l10 -10" /></svg>',
|
||||
radio: {
|
||||
checked: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" style="padding: 2px"><path fill="currentColor" d="M10,5 C7.2,5 5,7.2 5,10 C5,12.8 7.2,15 10,15 C12.8,15 15,12.8 15,10 C15,7.2 12.8,5 10,5 L10,5 Z M10,0 C4.5,0 0,4.5 0,10 C0,15.5 4.5,20 10,20 C15.5,20 20,15.5 20,10 C20,4.5 15.5,0 10,0 L10,0 Z M10,18 C5.6,18 2,14.4 2,10 C2,5.6 5.6,2 10,2 C14.4,2 18,5.6 18,10 C18,14.4 14.4,18 10,18 L10,18 Z" /></svg>',
|
||||
unchecked: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" style="padding: 2px"><path fill="currentColor" d="M10,0 C4.5,0 0,4.5 0,10 C0,15.5 4.5,20 10,20 C15.5,20 20,15.5 20,10 C20,4.5 15.5,0 10,0 L10,0 Z M10,18 C5.6,18 2,14.4 2,10 C2,5.6 5.6,2 10,2 C14.4,2 18,5.6 18,10 C18,14.4 14.4,18 10,18 L10,18 Z" /></svg>',
|
||||
checked:
|
||||
'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" style="padding: 2px"><path fill="currentColor" d="M10,5 C7.2,5 5,7.2 5,10 C5,12.8 7.2,15 10,15 C12.8,15 15,12.8 15,10 C15,7.2 12.8,5 10,5 L10,5 Z M10,0 C4.5,0 0,4.5 0,10 C0,15.5 4.5,20 10,20 C15.5,20 20,15.5 20,10 C20,4.5 15.5,0 10,0 L10,0 Z M10,18 C5.6,18 2,14.4 2,10 C2,5.6 5.6,2 10,2 C14.4,2 18,5.6 18,10 C18,14.4 14.4,18 10,18 L10,18 Z" /></svg>',
|
||||
unchecked:
|
||||
'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" style="padding: 2px"><path fill="currentColor" d="M10,0 C4.5,0 0,4.5 0,10 C0,15.5 4.5,20 10,20 C15.5,20 20,15.5 20,10 C20,4.5 15.5,0 10,0 L10,0 Z M10,18 C5.6,18 2,14.4 2,10 C2,5.6 5.6,2 10,2 C14.4,2 18,5.6 18,10 C18,14.4 14.4,18 10,18 L10,18 Z" /></svg>',
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@ -27,8 +27,12 @@ export const createPanel = (
|
||||
if (item.checked) iconWrapper.innerHTML = Icons.radio.checked;
|
||||
else iconWrapper.innerHTML = Icons.radio.unchecked;
|
||||
} else {
|
||||
const iconURL = typeof item.icon === 'string' ?
|
||||
await window.ipcRenderer.invoke('image-path-to-data-url') as string : item.icon?.toDataURL();
|
||||
const iconURL =
|
||||
typeof item.icon === 'string'
|
||||
? ((await window.ipcRenderer.invoke(
|
||||
'image-path-to-data-url',
|
||||
)) as string)
|
||||
: item.icon?.toDataURL();
|
||||
|
||||
if (iconURL) iconWrapper.style.background = `url(${iconURL})`;
|
||||
}
|
||||
@ -36,7 +40,8 @@ export const createPanel = (
|
||||
|
||||
const radioGroups: [MenuItem, HTMLElement][] = [];
|
||||
items.map((item) => {
|
||||
if (item.type === 'separator') return panel.appendChild(document.createElement('menu-separator'));
|
||||
if (item.type === 'separator')
|
||||
return panel.appendChild(document.createElement('menu-separator'));
|
||||
|
||||
const menu = document.createElement('menu-item');
|
||||
const iconWrapper = document.createElement('menu-icon');
|
||||
@ -47,7 +52,10 @@ export const createPanel = (
|
||||
|
||||
menu.addEventListener('click', async () => {
|
||||
await window.ipcRenderer.invoke('menu-event', item.commandId);
|
||||
const menuItem = await window.ipcRenderer.invoke('get-menu-by-id', item.commandId) as MenuItem | null;
|
||||
const menuItem = (await window.ipcRenderer.invoke(
|
||||
'get-menu-by-id',
|
||||
item.commandId,
|
||||
)) as MenuItem | null;
|
||||
|
||||
if (menuItem) {
|
||||
updateIconState(iconWrapper, menuItem);
|
||||
@ -56,10 +64,13 @@ export const createPanel = (
|
||||
await Promise.all(
|
||||
radioGroups.map(async ([item, iconWrapper]) => {
|
||||
if (item.commandId === menuItem.commandId) return;
|
||||
const newItem = await window.ipcRenderer.invoke('get-menu-by-id', item.commandId) as MenuItem | null;
|
||||
const newItem = (await window.ipcRenderer.invoke(
|
||||
'get-menu-by-id',
|
||||
item.commandId,
|
||||
)) as MenuItem | null;
|
||||
|
||||
if (newItem) updateIconState(iconWrapper, newItem);
|
||||
})
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -74,10 +85,15 @@ export const createPanel = (
|
||||
subMenuIcon.appendChild(ElementFromHtml(Icons.submenu));
|
||||
menu.appendChild(subMenuIcon);
|
||||
|
||||
const [child, , children] = createPanel(parent, menu, item.submenu?.items ?? [], {
|
||||
placement: 'right',
|
||||
order: (options?.order ?? 0) + 1,
|
||||
});
|
||||
const [child, , children] = createPanel(
|
||||
parent,
|
||||
menu,
|
||||
item.submenu?.items ?? [],
|
||||
{
|
||||
placement: 'right',
|
||||
order: (options?.order ?? 0) + 1,
|
||||
},
|
||||
);
|
||||
|
||||
childPanels.push(child);
|
||||
children.push(...children);
|
||||
@ -106,7 +122,10 @@ export const createPanel = (
|
||||
// long lists to squeeze their children at the bottom of the screen
|
||||
// (This needs to be done *after* setAttribute)
|
||||
panel.classList.remove('position-by-bottom');
|
||||
if (options.placement === 'right' && panel.scrollHeight > panel.clientHeight ) {
|
||||
if (
|
||||
options.placement === 'right' &&
|
||||
panel.scrollHeight > panel.clientHeight
|
||||
) {
|
||||
panel.style.setProperty('--y', `${rect.y + rect.height}px`);
|
||||
panel.classList.add('position-by-bottom');
|
||||
}
|
||||
@ -119,16 +138,17 @@ export const createPanel = (
|
||||
|
||||
document.body.addEventListener('click', (event) => {
|
||||
const path = event.composedPath();
|
||||
const isInside = path.some((it) => it === panel || it === anchor || childPanels.includes(it as HTMLElement));
|
||||
const isInside = path.some(
|
||||
(it) =>
|
||||
it === panel ||
|
||||
it === anchor ||
|
||||
childPanels.includes(it as HTMLElement),
|
||||
);
|
||||
|
||||
if (!isInside) close();
|
||||
});
|
||||
|
||||
parent.appendChild(panel);
|
||||
|
||||
return [
|
||||
panel,
|
||||
{ isOpened, close, open },
|
||||
childPanels,
|
||||
] as const;
|
||||
return [panel, { isOpened, close, open }, childPanels] as const;
|
||||
};
|
||||
|
||||
@ -12,9 +12,13 @@ import type { RendererContext } from '@/types/contexts';
|
||||
import type { InAppMenuConfig } from '@/plugins/in-app-menu/index';
|
||||
|
||||
const isMacOS = navigator.userAgent.includes('Macintosh');
|
||||
const isNotWindowsOrMacOS = !navigator.userAgent.includes('Windows') && !isMacOS;
|
||||
const isNotWindowsOrMacOS =
|
||||
!navigator.userAgent.includes('Windows') && !isMacOS;
|
||||
|
||||
export const onRendererLoad = async ({ getConfig, ipc: { invoke, on } }: RendererContext<InAppMenuConfig>) => {
|
||||
export const onRendererLoad = async ({
|
||||
getConfig,
|
||||
ipc: { invoke, on },
|
||||
}: RendererContext<InAppMenuConfig>) => {
|
||||
const config = await getConfig();
|
||||
|
||||
const hideDOMWindowControls = config.hideDOMWindowControls;
|
||||
@ -70,7 +74,6 @@ export const onRendererLoad = async ({ getConfig, ipc: { invoke, on } }: Rendere
|
||||
titleBar.appendChild(logo);
|
||||
|
||||
const addWindowControls = async () => {
|
||||
|
||||
// Create window control buttons
|
||||
const minimizeButton = document.createElement('button');
|
||||
minimizeButton.classList.add('window-control');
|
||||
@ -124,12 +127,20 @@ export const onRendererLoad = async ({ getConfig, ipc: { invoke, on } }: Rendere
|
||||
if (navBar) {
|
||||
const observer = new MutationObserver((mutations) => {
|
||||
mutations.forEach(() => {
|
||||
titleBar.style.setProperty('--titlebar-background-color', navBar.style.backgroundColor);
|
||||
document.querySelector('html')!.style.setProperty('--titlebar-background-color', navBar.style.backgroundColor);
|
||||
titleBar.style.setProperty(
|
||||
'--titlebar-background-color',
|
||||
navBar.style.backgroundColor,
|
||||
);
|
||||
document
|
||||
.querySelector('html')!
|
||||
.style.setProperty(
|
||||
'--titlebar-background-color',
|
||||
navBar.style.backgroundColor,
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
observer.observe(navBar, { attributes : true, attributeFilter : ['style'] });
|
||||
observer.observe(navBar, { attributes: true, attributeFilter: ['style'] });
|
||||
}
|
||||
|
||||
const updateMenu = async () => {
|
||||
@ -139,12 +150,16 @@ export const onRendererLoad = async ({ getConfig, ipc: { invoke, on } }: Rendere
|
||||
});
|
||||
panelClosers = [];
|
||||
|
||||
const menu = await invoke('get-menu') as Menu | null;
|
||||
const menu = (await invoke('get-menu')) as Menu | null;
|
||||
if (!menu) return;
|
||||
|
||||
menu.items.forEach((menuItem) => {
|
||||
const menu = document.createElement('menu-button');
|
||||
const [, { close: closer }] = createPanel(titleBar, menu, menuItem.submenu?.items ?? []);
|
||||
const [, { close: closer }] = createPanel(
|
||||
titleBar,
|
||||
menu,
|
||||
menuItem.submenu?.items ?? [],
|
||||
);
|
||||
panelClosers.push(closer);
|
||||
|
||||
menu.append(menuItem.label);
|
||||
@ -153,7 +168,8 @@ export const onRendererLoad = async ({ getConfig, ipc: { invoke, on } }: Rendere
|
||||
menu.style.visibility = 'hidden';
|
||||
}
|
||||
});
|
||||
if (isNotWindowsOrMacOS && !hideDOMWindowControls) await addWindowControls();
|
||||
if (isNotWindowsOrMacOS && !hideDOMWindowControls)
|
||||
await addWindowControls();
|
||||
};
|
||||
await updateMenu();
|
||||
|
||||
@ -164,13 +180,21 @@ export const onRendererLoad = async ({ getConfig, ipc: { invoke, on } }: Rendere
|
||||
});
|
||||
on('refresh-in-app-menu', () => updateMenu());
|
||||
on('window-maximize', () => {
|
||||
if (isNotWindowsOrMacOS && !hideDOMWindowControls && maximizeButton.firstChild) {
|
||||
if (
|
||||
isNotWindowsOrMacOS &&
|
||||
!hideDOMWindowControls &&
|
||||
maximizeButton.firstChild
|
||||
) {
|
||||
maximizeButton.removeChild(maximizeButton.firstChild);
|
||||
maximizeButton.appendChild(unmaximize);
|
||||
}
|
||||
});
|
||||
on('window-unmaximize', () => {
|
||||
if (isNotWindowsOrMacOS && !hideDOMWindowControls && maximizeButton.firstChild) {
|
||||
if (
|
||||
isNotWindowsOrMacOS &&
|
||||
!hideDOMWindowControls &&
|
||||
maximizeButton.firstChild
|
||||
) {
|
||||
maximizeButton.removeChild(maximizeButton.firstChild);
|
||||
maximizeButton.appendChild(unmaximize);
|
||||
}
|
||||
@ -187,6 +211,9 @@ export const onPlayerApiReady = () => {
|
||||
const htmlHeadStyle = document.querySelector('head > div > style');
|
||||
if (htmlHeadStyle) {
|
||||
// HACK: This is a hack to remove the scrollbar width
|
||||
htmlHeadStyle.innerHTML = htmlHeadStyle.innerHTML.replace('html::-webkit-scrollbar {width: var(--ytmusic-scrollbar-width);', 'html::-webkit-scrollbar {');
|
||||
htmlHeadStyle.innerHTML = htmlHeadStyle.innerHTML.replace(
|
||||
'html::-webkit-scrollbar {width: var(--ytmusic-scrollbar-width);',
|
||||
'html::-webkit-scrollbar {',
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
@ -27,7 +27,9 @@ title-bar {
|
||||
background-color: var(--titlebar-background-color, #030303);
|
||||
user-select: none;
|
||||
|
||||
transition: opacity 200ms ease 0s, background-color 300ms cubic-bezier(0.2, 0, 0.6, 1) 0s;
|
||||
transition:
|
||||
opacity 200ms ease 0s,
|
||||
background-color 300ms cubic-bezier(0.2, 0, 0.6, 1) 0s;
|
||||
}
|
||||
|
||||
menu-button {
|
||||
@ -64,18 +66,26 @@ menu-panel {
|
||||
padding: 4px;
|
||||
border-radius: 8px;
|
||||
pointer-events: none;
|
||||
background-color: color-mix(in srgb, var(--titlebar-background-color, #030303) 50%, rgba(0, 0, 0, 0.1));
|
||||
background-color: color-mix(
|
||||
in srgb,
|
||||
var(--titlebar-background-color, #030303) 50%,
|
||||
rgba(0, 0, 0, 0.1)
|
||||
);
|
||||
backdrop-filter: blur(8px);
|
||||
box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.05), 0 2px 8px rgba(0, 0, 0, 0.2);
|
||||
box-shadow:
|
||||
0 0 0 1px rgba(0, 0, 0, 0.05),
|
||||
0 2px 8px rgba(0, 0, 0, 0.2);
|
||||
|
||||
z-index: 0;
|
||||
opacity: 0;
|
||||
transform: scale(0.8);
|
||||
transform-origin: top left;
|
||||
|
||||
transition: opacity 200ms ease 0s, transform 200ms ease 0s;
|
||||
transition:
|
||||
opacity 200ms ease 0s,
|
||||
transform 200ms ease 0s;
|
||||
}
|
||||
menu-panel[open="true"] {
|
||||
menu-panel[open='true'] {
|
||||
pointer-events: all;
|
||||
opacity: 1;
|
||||
transform: scale(1);
|
||||
@ -159,22 +169,32 @@ ytmusic-app-layout {
|
||||
margin-top: var(--menu-bar-height, 36px) !important;
|
||||
}
|
||||
|
||||
ytmusic-app-layout>[slot=nav-bar], #nav-bar-background.ytmusic-app-layout {
|
||||
ytmusic-app-layout > [slot='nav-bar'],
|
||||
#nav-bar-background.ytmusic-app-layout {
|
||||
top: var(--menu-bar-height, 36px) !important;
|
||||
}
|
||||
#nav-bar-divider.ytmusic-app-layout {
|
||||
top: calc(var(--ytmusic-nav-bar-height) + var(--menu-bar-height, 36px)) !important;
|
||||
top: calc(
|
||||
var(--ytmusic-nav-bar-height) + var(--menu-bar-height, 36px)
|
||||
) !important;
|
||||
}
|
||||
ytmusic-app[is-bauhaus-sidenav-enabled] #guide-spacer.ytmusic-app,
|
||||
ytmusic-app[is-bauhaus-sidenav-enabled] #mini-guide-spacer.ytmusic-app {
|
||||
margin-top: calc(var(--ytmusic-nav-bar-height) + var(--menu-bar-height, 36px)) !important;
|
||||
margin-top: calc(
|
||||
var(--ytmusic-nav-bar-height) + var(--menu-bar-height, 36px)
|
||||
) !important;
|
||||
}
|
||||
|
||||
ytmusic-app-layout>[slot=player-page] {
|
||||
ytmusic-app-layout > [slot='player-page'] {
|
||||
margin-top: var(--menu-bar-height);
|
||||
height: calc(100vh - var(--menu-bar-height) - var(--ytmusic-nav-bar-height) - var(--ytmusic-player-bar-height)) !important;
|
||||
height: calc(
|
||||
100vh - var(--menu-bar-height) - var(--ytmusic-nav-bar-height) -
|
||||
var(--ytmusic-player-bar-height)
|
||||
) !important;
|
||||
}
|
||||
|
||||
ytmusic-guide-renderer {
|
||||
height: calc(100vh - var(--menu-bar-height) - var(--ytmusic-nav-bar-height)) !important;
|
||||
height: calc(
|
||||
100vh - var(--menu-bar-height) - var(--ytmusic-nav-bar-height)
|
||||
) !important;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user