mirror of
https://github.com/th-ch/youtube-music.git
synced 2026-01-09 17:51:46 +00:00
13
assets/youtube-music.svg
Normal file
13
assets/youtube-music.svg
Normal file
@ -0,0 +1,13 @@
|
||||
<svg xmlns:x="http://ns.adobe.com/Extensibility/1.0/" xmlns:i="http://ns.adobe.com/AdobeIllustrator/10.0/" xmlns:graph="http://ns.adobe.com/Graphs/1.0/" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" id="Layer_1" x="0px" y="0px" viewBox="0 0 176 176" enable-background="new 0 0 176 176" xml:space="preserve">
|
||||
<metadata>
|
||||
<sfw xmlns="http://ns.adobe.com/SaveForWeb/1.0/">
|
||||
<slices/>
|
||||
<sliceSourceBounds bottomLeftOrigin="true" height="176" width="176" x="8" y="-184"/>
|
||||
</sfw>
|
||||
</metadata>
|
||||
<g id="XMLID_167_">
|
||||
<circle id="XMLID_791_" fill="#FF0000" cx="88" cy="88" r="88"/>
|
||||
<path id="XMLID_42_" fill="#FFFFFF" d="M88,46c23.1,0,42,18.8,42,42s-18.8,42-42,42s-42-18.8-42-42S64.9,46,88,46 M88,42 c-25.4,0-46,20.6-46,46s20.6,46,46,46s46-20.6,46-46S113.4,42,88,42L88,42z"/>
|
||||
<polygon id="XMLID_274_" fill="#FFFFFF" points="72,111 111,87 72,65 "/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 902 B |
7
index.ts
7
index.ts
@ -136,7 +136,12 @@ function createMainWindow() {
|
||||
sandbox: false,
|
||||
}),
|
||||
},
|
||||
frame: !is.macOS() && !useInlineMenu,
|
||||
frame: !is.macOS() && !is.linux() && !useInlineMenu,
|
||||
titleBarOverlay: {
|
||||
color: '#00000000',
|
||||
symbolColor: '#ffffff',
|
||||
height: 36,
|
||||
},
|
||||
titleBarStyle: useInlineMenu
|
||||
? 'hidden'
|
||||
: (is.macOS()
|
||||
|
||||
9
package-lock.json
generated
9
package-lock.json
generated
@ -20,7 +20,6 @@
|
||||
"butterchurn-presets": "2.4.7",
|
||||
"conf": "10.2.0",
|
||||
"custom-electron-prompt": "1.5.7",
|
||||
"custom-electron-titlebar": "4.1.6",
|
||||
"electron-better-web-request": "1.0.1",
|
||||
"electron-debug": "3.2.0",
|
||||
"electron-is": "3.0.0",
|
||||
@ -3184,14 +3183,6 @@
|
||||
"electron": ">=10.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/custom-electron-titlebar": {
|
||||
"version": "4.1.6",
|
||||
"resolved": "https://registry.npmjs.org/custom-electron-titlebar/-/custom-electron-titlebar-4.1.6.tgz",
|
||||
"integrity": "sha512-AGULUZMxhEZDpl0Z1jfZzXgQEdhAPe8YET0dYQA/19t8oCrTFzF2PzdvJNCmxGU4Ai3jPWVeCPKg4vM7ffU0Mg==",
|
||||
"peerDependencies": {
|
||||
"electron": ">20"
|
||||
}
|
||||
},
|
||||
"node_modules/dbus-next": {
|
||||
"version": "0.9.2",
|
||||
"resolved": "https://registry.npmjs.org/dbus-next/-/dbus-next-0.9.2.tgz",
|
||||
|
||||
@ -142,7 +142,6 @@
|
||||
"butterchurn-presets": "2.4.7",
|
||||
"conf": "10.2.0",
|
||||
"custom-electron-prompt": "1.5.7",
|
||||
"custom-electron-titlebar": "4.1.6",
|
||||
"electron-better-web-request": "1.0.1",
|
||||
"electron-debug": "3.2.0",
|
||||
"electron-is": "3.0.0",
|
||||
|
||||
@ -1,27 +1,58 @@
|
||||
import path from 'node:path';
|
||||
|
||||
import { register } from 'electron-localshortcut';
|
||||
// eslint-disable-next-line import/no-unresolved
|
||||
import { attachTitlebarToWindow, setupTitlebar } from 'custom-electron-titlebar/main';
|
||||
|
||||
import { BrowserWindow } from 'electron';
|
||||
import { BrowserWindow, Menu, MenuItem, ipcMain } from 'electron';
|
||||
|
||||
import { injectCSS } from '../utils';
|
||||
|
||||
|
||||
setupTitlebar();
|
||||
|
||||
// Tracks menu visibility
|
||||
|
||||
export default (win: BrowserWindow) => {
|
||||
// Css for custom scrollbar + disable drag area(was causing bugs)
|
||||
injectCSS(win.webContents, path.join(__dirname, 'style.css'));
|
||||
injectCSS(win.webContents, path.join(__dirname, 'titlebar.css'));
|
||||
|
||||
win.once('ready-to-show', () => {
|
||||
attachTitlebarToWindow(win);
|
||||
|
||||
register(win, '`', () => {
|
||||
win.webContents.send('toggleMenu');
|
||||
});
|
||||
});
|
||||
|
||||
ipcMain.handle(
|
||||
'get-menu',
|
||||
() => JSON.parse(JSON.stringify(
|
||||
Menu.getApplicationMenu(),
|
||||
(key: string, value: unknown) => (key !== 'commandsMap' && key !== 'menu') ? value : undefined),
|
||||
),
|
||||
);
|
||||
|
||||
const getMenuItemById = (commandId: number): MenuItem | null => {
|
||||
const menu = Menu.getApplicationMenu();
|
||||
|
||||
let target: MenuItem | null = null;
|
||||
const stack = [...menu?.items ?? []];
|
||||
while (stack.length > 0) {
|
||||
const now = stack.shift();
|
||||
now?.submenu?.items.forEach((item) => stack.push(item));
|
||||
|
||||
if (now?.commandId === commandId) {
|
||||
target = now;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return target;
|
||||
};
|
||||
|
||||
ipcMain.handle('menu-event', (event, commandId: number) => {
|
||||
const target = getMenuItemById(commandId);
|
||||
if (target) target.click(undefined, BrowserWindow.fromWebContents(event.sender), event.sender);
|
||||
});
|
||||
|
||||
ipcMain.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),
|
||||
);
|
||||
});
|
||||
};
|
||||
|
||||
@ -1,9 +0,0 @@
|
||||
declare module 'custom-electron-titlebar' {
|
||||
// eslint-disable-next-line import/no-unresolved
|
||||
import OriginalTitlebar from 'custom-electron-titlebar/dist/titlebar';
|
||||
// eslint-disable-next-line import/no-unresolved
|
||||
import { Color as OriginalColor } from 'custom-electron-titlebar/dist/vs/base/common/color';
|
||||
|
||||
export const Color: typeof OriginalColor;
|
||||
export const Titlebar: typeof OriginalTitlebar;
|
||||
}
|
||||
@ -1,12 +1,12 @@
|
||||
import path from 'node:path';
|
||||
|
||||
import { ipcRenderer, Menu } from 'electron';
|
||||
// eslint-disable-next-line import/no-unresolved
|
||||
import { Color, Titlebar } from 'custom-electron-titlebar';
|
||||
|
||||
import config from '../../config';
|
||||
import { createPanel } from './menu/panel';
|
||||
|
||||
import { ElementFromFile } from '../utils';
|
||||
import { isEnabled } from '../../config/plugins';
|
||||
|
||||
import type { FastAverageColorResult } from 'fast-average-color';
|
||||
|
||||
type ElectronCSSStyleDeclaration = CSSStyleDeclaration & { webkitAppRegion: 'drag' | 'no-drag' };
|
||||
type ElectronHTMLElement = HTMLElement & { style: ElectronCSSStyleDeclaration };
|
||||
|
||||
@ -15,60 +15,60 @@ function $<E extends Element = Element>(selector: string) {
|
||||
}
|
||||
|
||||
export default () => {
|
||||
const visible = () => !!($('.cet-menubar')?.firstChild);
|
||||
const bar = new Titlebar({
|
||||
icon: 'https://cdn-icons-png.flaticon.com/512/5358/5358672.png',
|
||||
backgroundColor: Color.fromHex('#050505'),
|
||||
itemBackgroundColor: Color.fromHex('#1d1d1d') ,
|
||||
svgColor: Color.WHITE,
|
||||
menu: config.get('options.hideMenu') ? null as unknown as Menu : undefined,
|
||||
});
|
||||
bar.updateTitle(' ');
|
||||
const titleBar = document.createElement('title-bar');
|
||||
const navBar = document.querySelector<HTMLDivElement>('#nav-bar-background');
|
||||
|
||||
const logo = ElementFromFile(path.join(__dirname, '../../assets/youtube-music.svg'));
|
||||
logo.classList.add('title-bar-icon');
|
||||
|
||||
titleBar.appendChild(logo);
|
||||
document.body.appendChild(titleBar);
|
||||
|
||||
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);
|
||||
});
|
||||
});
|
||||
|
||||
observer.observe(navBar, { attributes : true, attributeFilter : ['style'] });
|
||||
}
|
||||
|
||||
const updateMenu = async () => {
|
||||
const children = [...titleBar.children];
|
||||
children.forEach((child) => {
|
||||
if (child !== logo) child.remove();
|
||||
});
|
||||
|
||||
const menu = await ipcRenderer.invoke('get-menu') as Menu | null;
|
||||
if (!menu) return;
|
||||
|
||||
menu.items.forEach((menuItem) => {
|
||||
const menu = document.createElement('menu-button');
|
||||
createPanel(titleBar, menu, menuItem.submenu?.items ?? []);
|
||||
|
||||
menu.append(menuItem.label);
|
||||
titleBar.appendChild(menu);
|
||||
});
|
||||
};
|
||||
updateMenu();
|
||||
|
||||
document.title = 'Youtube Music';
|
||||
|
||||
const toggleMenu = () => {
|
||||
if (visible()) {
|
||||
bar.updateMenu(null as unknown as Menu);
|
||||
} else {
|
||||
bar.refreshMenu();
|
||||
}
|
||||
};
|
||||
|
||||
$('.cet-window-icon')?.addEventListener('click', toggleMenu);
|
||||
ipcRenderer.on('toggleMenu', toggleMenu);
|
||||
|
||||
ipcRenderer.on('refreshMenu', () => {
|
||||
if (visible()) {
|
||||
bar.refreshMenu();
|
||||
}
|
||||
updateMenu();
|
||||
});
|
||||
|
||||
if (isEnabled('album-color-theme')) {
|
||||
ipcRenderer.on('album-color-changed', (_, albumColor: FastAverageColorResult) => {
|
||||
if (albumColor) {
|
||||
bar.updateBackground(Color.fromHex(albumColor.hexa));
|
||||
} else {
|
||||
bar.updateBackground(Color.fromHex('#050505'));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (isEnabled('picture-in-picture')) {
|
||||
ipcRenderer.on('pip-toggle', () => {
|
||||
bar.refreshMenu();
|
||||
updateMenu();
|
||||
});
|
||||
}
|
||||
|
||||
// Increases the right margin of Navbar background when the scrollbar is visible to avoid blocking it (z-index doesn't affect it)
|
||||
document.addEventListener('apiLoaded', () => {
|
||||
setNavbarMargin();
|
||||
const playPageObserver = new MutationObserver(setNavbarMargin);
|
||||
const appLayout = $('ytmusic-app-layout');
|
||||
if (appLayout) {
|
||||
playPageObserver.observe(appLayout, { attributeFilter: ['player-page-open_', 'playerPageOpen_'] });
|
||||
}
|
||||
setupSearchOpenObserver();
|
||||
setupMenuOpenObserver();
|
||||
}, { once: true, passive: true });
|
||||
};
|
||||
|
||||
@ -84,33 +84,3 @@ function setupSearchOpenObserver() {
|
||||
searchOpenObserver.observe(searchBox, { attributeFilter: ['opened'] });
|
||||
}
|
||||
}
|
||||
|
||||
function setupMenuOpenObserver() {
|
||||
const cetMenubar = $('.cet-menubar');
|
||||
if (cetMenubar) {
|
||||
const menuOpenObserver = new MutationObserver(() => {
|
||||
let isOpen = false;
|
||||
for (const child of cetMenubar.children) {
|
||||
if (child.classList.contains('open')) {
|
||||
isOpen = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
const navBarBackground = $<ElectronHTMLElement>('#nav-bar-background');
|
||||
if (navBarBackground) {
|
||||
navBarBackground.style.webkitAppRegion = isOpen ? 'no-drag' : 'drag';
|
||||
}
|
||||
});
|
||||
menuOpenObserver.observe(cetMenubar, { subtree: true, attributeFilter: ['class'] });
|
||||
}
|
||||
}
|
||||
|
||||
function setNavbarMargin() {
|
||||
const navBarBackground = $<HTMLElement>('#nav-bar-background');
|
||||
if (navBarBackground) {
|
||||
navBarBackground.style.right
|
||||
= $<HTMLElement & { playerPageOpen_: boolean }>('ytmusic-app-layout')?.playerPageOpen_
|
||||
? '0px'
|
||||
: '12px';
|
||||
}
|
||||
}
|
||||
|
||||
10
plugins/in-app-menu/menu/icons.ts
Normal file
10
plugins/in-app-menu/menu/icons.ts
Normal file
@ -0,0 +1,10 @@
|
||||
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>',
|
||||
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>',
|
||||
},
|
||||
};
|
||||
|
||||
export default Icons;
|
||||
125
plugins/in-app-menu/menu/panel.ts
Normal file
125
plugins/in-app-menu/menu/panel.ts
Normal file
@ -0,0 +1,125 @@
|
||||
import { nativeImage, type MenuItem, ipcRenderer, Menu } from 'electron';
|
||||
|
||||
import Icons from './icons';
|
||||
|
||||
import { ElementFromHtml } from '../../utils';
|
||||
|
||||
interface PanelOptions {
|
||||
placement?: 'bottom' | 'right';
|
||||
order?: number;
|
||||
}
|
||||
|
||||
export const createPanel = (
|
||||
parent: HTMLElement,
|
||||
anchor: HTMLElement,
|
||||
items: MenuItem[],
|
||||
options: PanelOptions = { placement: 'bottom', order: 0 },
|
||||
) => {
|
||||
const childPanels: HTMLElement[] = [];
|
||||
const panel = document.createElement('menu-panel');
|
||||
panel.style.zIndex = `${options.order}`;
|
||||
|
||||
const updateIconState = (iconWrapper: HTMLElement, item: MenuItem) => {
|
||||
if (item.type === 'checkbox') {
|
||||
if (item.checked) iconWrapper.innerHTML = Icons.checkbox;
|
||||
else iconWrapper.innerHTML = '';
|
||||
} else if (item.type === 'radio') {
|
||||
if (item.checked) iconWrapper.innerHTML = Icons.radio.checked;
|
||||
else iconWrapper.innerHTML = Icons.radio.unchecked;
|
||||
} else {
|
||||
const nativeImageIcon = typeof item.icon === 'string' ? nativeImage.createFromPath(item.icon) : item.icon;
|
||||
const iconURL = nativeImageIcon?.toDataURL();
|
||||
|
||||
if (iconURL) iconWrapper.style.background = `url(${iconURL})`;
|
||||
}
|
||||
};
|
||||
|
||||
const radioGroups: [MenuItem, HTMLElement][] = [];
|
||||
items.map((item) => {
|
||||
if (item.type === 'separator') return panel.appendChild(document.createElement('menu-separator'));
|
||||
|
||||
const menu = document.createElement('menu-item');
|
||||
const iconWrapper = document.createElement('menu-icon');
|
||||
|
||||
updateIconState(iconWrapper, item);
|
||||
menu.appendChild(iconWrapper);
|
||||
menu.append(item.label);
|
||||
|
||||
menu.addEventListener('click', async () => {
|
||||
await ipcRenderer.invoke('menu-event', item.commandId);
|
||||
const menuItem = await ipcRenderer.invoke('get-menu-by-id', item.commandId) as MenuItem | null;
|
||||
|
||||
if (menuItem) {
|
||||
updateIconState(iconWrapper, menuItem);
|
||||
|
||||
if (menuItem.type === 'radio') {
|
||||
await Promise.all(
|
||||
radioGroups.map(async ([item, iconWrapper]) => {
|
||||
if (item.commandId === menuItem.commandId) return;
|
||||
const newItem = await ipcRenderer.invoke('get-menu-by-id', item.commandId) as MenuItem | null;
|
||||
|
||||
if (newItem) updateIconState(iconWrapper, newItem);
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (item.type === 'radio') {
|
||||
radioGroups.push([item, iconWrapper]);
|
||||
}
|
||||
|
||||
if (item.type === 'submenu') {
|
||||
const subMenuIcon = document.createElement('menu-icon');
|
||||
subMenuIcon.appendChild(ElementFromHtml(Icons.submenu));
|
||||
menu.appendChild(subMenuIcon);
|
||||
|
||||
const [child, , children] = createPanel(parent, menu, item.submenu?.items ?? [], {
|
||||
placement: 'right',
|
||||
order: (options?.order ?? 0) + 1,
|
||||
});
|
||||
|
||||
childPanels.push(child);
|
||||
children.push(...children);
|
||||
}
|
||||
|
||||
panel.appendChild(menu);
|
||||
});
|
||||
|
||||
/* methods */
|
||||
const isOpened = () => panel.getAttribute('open') === 'true';
|
||||
const close = () => panel.setAttribute('open', 'false');
|
||||
const open = () => {
|
||||
const rect = anchor.getBoundingClientRect();
|
||||
|
||||
if (options.placement === 'bottom') {
|
||||
panel.style.setProperty('--x', `${rect.x}px`);
|
||||
panel.style.setProperty('--y', `${rect.y + rect.height}px`);
|
||||
} else {
|
||||
panel.style.setProperty('--x', `${rect.x + rect.width}px`);
|
||||
panel.style.setProperty('--y', `${rect.y}px`);
|
||||
}
|
||||
|
||||
panel.setAttribute('open', 'true');
|
||||
};
|
||||
|
||||
anchor.addEventListener('click', () => {
|
||||
if (isOpened()) close();
|
||||
else open();
|
||||
});
|
||||
|
||||
document.body.addEventListener('click', (event) => {
|
||||
const path = event.composedPath();
|
||||
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;
|
||||
};
|
||||
@ -1,118 +0,0 @@
|
||||
/* increase font size for menu and menuItems */
|
||||
.titlebar,
|
||||
.menubar-menu-container .action-label {
|
||||
font-size: 14px !important;
|
||||
}
|
||||
|
||||
/* fixes nav-bar-background opacity bug, reposition it, and allows clicking scrollbar through it */
|
||||
#nav-bar-background {
|
||||
opacity: 1 !important;
|
||||
pointer-events: none !important;
|
||||
top: 30px !important;
|
||||
height: 75px !important;
|
||||
}
|
||||
|
||||
/* fix top gap between nav-bar and browse-page */
|
||||
#browse-page {
|
||||
padding-top: 0 !important;
|
||||
}
|
||||
|
||||
/* https://github.com/organization/youtube-music-next/issues/4 */
|
||||
#sections {
|
||||
padding-top: 30px !important;
|
||||
}
|
||||
|
||||
/* fix navbar hiding library items */
|
||||
ytmusic-section-list-renderer[page-type="MUSIC_PAGE_TYPE_LIBRARY_CONTENT_LANDING_PAGE"],
|
||||
ytmusic-section-list-renderer[page-type="MUSIC_PAGE_TYPE_PRIVATELY_OWNED_CONTENT_LANDING_PAGE"] {
|
||||
top: 50px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
/* remove window dragging for nav bar (conflict with titlebar drag) */
|
||||
ytmusic-nav-bar,
|
||||
.tab-titleiron-icon,
|
||||
ytmusic-pivot-bar-item-renderer {
|
||||
-webkit-app-region: unset !important;
|
||||
}
|
||||
|
||||
/* move up item selection renderers */
|
||||
ytmusic-item-section-renderer.stuck #header.ytmusic-item-section-renderer,
|
||||
ytmusic-tabs.stuck {
|
||||
top: calc(var(--ytmusic-nav-bar-height) - 15px) !important;
|
||||
}
|
||||
|
||||
/* fix weird positioning in search screen*/
|
||||
ytmusic-header-renderer.ytmusic-search-page {
|
||||
position: unset !important;
|
||||
}
|
||||
|
||||
/* Move navBar downwards */
|
||||
ytmusic-nav-bar[slot="nav-bar"] {
|
||||
top: 17px !important;
|
||||
}
|
||||
|
||||
/* fix page progress bar position*/
|
||||
yt-page-navigation-progress,
|
||||
#progress.yt-page-navigation-progress {
|
||||
top: 30px !important;
|
||||
}
|
||||
|
||||
/* custom scrollbar */
|
||||
::-webkit-scrollbar {
|
||||
width: 12px;
|
||||
background-color: #030303;
|
||||
border-radius: 100px;
|
||||
-moz-border-radius: 100px;
|
||||
-webkit-border-radius: 100px;
|
||||
}
|
||||
|
||||
/* hover effect for both scrollbar area, and scrollbar 'thumb' */
|
||||
::-webkit-scrollbar:hover {
|
||||
background-color: rgba(15, 15, 15, 0.699);
|
||||
}
|
||||
|
||||
/* the scrollbar 'thumb' ...that marque oval shape in a scrollbar */
|
||||
::-webkit-scrollbar-thumb:vertical {
|
||||
border: 2px solid rgba(0, 0, 0, 0);
|
||||
|
||||
background: #3a3a3a;
|
||||
background-clip: padding-box;
|
||||
border-radius: 100px;
|
||||
-moz-border-radius: 100px;
|
||||
-webkit-border-radius: 100px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb:vertical:active {
|
||||
background: #4d4c4c; /* some darker color when you click it */
|
||||
border-radius: 100px;
|
||||
-moz-border-radius: 100px;
|
||||
-webkit-border-radius: 100px;
|
||||
}
|
||||
|
||||
.cet-menubar-menu-container .cet-action-item {
|
||||
background-color: inherit
|
||||
}
|
||||
|
||||
/** hideMenu toggler **/
|
||||
.cet-window-icon {
|
||||
-webkit-app-region: no-drag;
|
||||
}
|
||||
|
||||
.cet-window-icon img {
|
||||
-webkit-user-drag: none;
|
||||
filter: invert(50%);
|
||||
}
|
||||
|
||||
/** make navbar draggable **/
|
||||
#nav-bar-background {
|
||||
-webkit-app-region: drag;
|
||||
}
|
||||
|
||||
ytmusic-nav-bar input,
|
||||
ytmusic-nav-bar span,
|
||||
ytmusic-nav-bar [role="button"],
|
||||
ytmusic-nav-bar yt-icon,
|
||||
tp-yt-iron-dropdown {
|
||||
-webkit-app-region: no-drag;
|
||||
}
|
||||
157
plugins/in-app-menu/titlebar.css
Normal file
157
plugins/in-app-menu/titlebar.css
Normal file
@ -0,0 +1,157 @@
|
||||
:root {
|
||||
--titlebar-background-color: #030303;
|
||||
--menu-bar-height: 36px;
|
||||
}
|
||||
|
||||
title-bar {
|
||||
-webkit-app-region: drag;
|
||||
box-sizing: border-box;
|
||||
|
||||
position: fixed;
|
||||
top: 0;
|
||||
z-index: 10000000;
|
||||
|
||||
width: 100%;
|
||||
height: var(--menu-bar-height, 36px);
|
||||
|
||||
display: flex;
|
||||
flex-flow: row;
|
||||
justify-content: flex-start;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
|
||||
color: #f1f1f1;
|
||||
font-size: 14px;
|
||||
padding: 4px 12px;
|
||||
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;
|
||||
}
|
||||
|
||||
menu-button {
|
||||
-webkit-app-region: none;
|
||||
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
align-self: stretch;
|
||||
|
||||
padding: 2px 8px;
|
||||
border-radius: 4px;
|
||||
|
||||
cursor: pointer;
|
||||
}
|
||||
menu-button:hover {
|
||||
background-color: rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
|
||||
menu-panel {
|
||||
position: fixed;
|
||||
top: var(--y, 0);
|
||||
left: var(--x, 0);
|
||||
|
||||
max-height: calc(100vh - var(--menu-bar-height, 36px) - 16px - var(--y, 0));
|
||||
|
||||
display: flex;
|
||||
flex-flow: column;
|
||||
justify-content: flex-start;
|
||||
align-items: stretch;
|
||||
gap: 0;
|
||||
|
||||
overflow: auto;
|
||||
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));
|
||||
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);
|
||||
|
||||
z-index: 0;
|
||||
opacity: 0;
|
||||
transform: scale(0.8);
|
||||
transform-origin: top left;
|
||||
|
||||
transition: opacity 200ms ease 0s, transform 200ms ease 0s;
|
||||
}
|
||||
menu-panel[open="true"] {
|
||||
pointer-events: all;
|
||||
opacity: 1;
|
||||
transform: scale(1);
|
||||
}
|
||||
|
||||
menu-item {
|
||||
-webkit-app-region: none;
|
||||
min-height: 32px;
|
||||
height: 32px;
|
||||
|
||||
display: grid;
|
||||
grid-template-columns: 32px 1fr minmax(32px, auto);
|
||||
justify-content: flex-start;
|
||||
align-items: center;
|
||||
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
}
|
||||
menu-item:hover {
|
||||
background-color: rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
|
||||
menu-item > menu-icon {
|
||||
height: 32px;
|
||||
padding: 4px;
|
||||
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
menu-separator {
|
||||
min-height: 1px;
|
||||
height: 1px;
|
||||
margin: 4px 0;
|
||||
|
||||
background-color: rgba(255, 255, 255, 0.2);
|
||||
}
|
||||
|
||||
/* classes */
|
||||
|
||||
.title-bar-icon {
|
||||
height: calc(100% - 8px);
|
||||
object-fit: cover;
|
||||
margin-left: -4px;
|
||||
}
|
||||
|
||||
/* youtube-music style */
|
||||
|
||||
ytmusic-app-layout {
|
||||
margin-top: var(--menu-bar-height, 36px) !important;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
html::-webkit-scrollbar {
|
||||
width: 12px !important;
|
||||
}
|
||||
|
||||
html::-webkit-scrollbar-thumb {
|
||||
border: solid 2px var(--titlebar-background-color, #030303) !important;
|
||||
border-radius: 100px !important;
|
||||
}
|
||||
|
||||
html::-webkit-scrollbar-track {
|
||||
background: var(--titlebar-background-color, #030303) !important;
|
||||
}
|
||||
|
||||
html::-webkit-scrollbar-track-piece:start {
|
||||
background: transparent;
|
||||
margin-top: var(--menu-bar-height, 36px);
|
||||
}
|
||||
Reference in New Issue
Block a user